typescript - TS 条件类型仅从联合中扩展一项
问题描述
我希望创建一个函数,它接受来自接口的键作为输入,Foo
仅限于可接受分配的键Foo
string
interface Foo {
a: string;
b?: string;
c?: string | boolean;
}
test("a");
test("b"); // Argument of type '"b"' is not assignable to parameter of type 'never'.ts(2345)
test("c"); // Argument of type '"c"' is not assignable to parameter of type 'never'.ts(2345)
function test<K extends keyof Foo>(key: Foo[K] extends string ? K : never) {}
上述(严格模式开启)失败b
并且c
- 有没有一种方法可以使用extends string
(或类似的)而不必完全匹配属性的类型?我对其他潜在类型不感兴趣,只是该类型可能是string
解决方案
因此,您显然正在寻找的测试是string extends Foo[K]
而不是Foo[K] extends string
:
function test<K extends keyof Foo>(key: string extends Foo[K] ? K : never) {}
test("a"); // okay
test("b"); // okay
test("c"); // okay
如果您考虑可分配性,T extends U
则意味着T
可以将 type 的值分配给 type 的变量U
。如果您将“可以接受赋值的属性Foo
”string
翻译成“可以将类型的值分配给按键索引string
的属性”,您会得到。在这种情况下,如果您有一个type变量、一个 type 变量和一个type变量,您应该能够编写并编译它。Foo
K
string extends Foo[K]
foo
Foo
k
K
s
string
foo[k] = s
测试Foo[K] extends string
将是您是否正在寻找Foo
可以将其分配给类型变量的属性,这string
恰恰相反:您可以编写s = foo[k]
.
这也正确地拒绝了非string
属性:
interface Foo {
d: number;
}
test("d"); // error!
// Argument of type '"d"' is not assignable to parameter of type 'never'.
它拒绝比更窄string
的类型的属性:
interface Foo {
e: "specificString";
}
test("e"); // error!
// Argument of type '"e"' is not assignable to parameter of type 'never'.
你不能foo.e = s
为任何旧字符串写s
,所以这就是拒绝的原因。(如果你需要接受这个,那么你要求表达更复杂的东西,而且也不清楚为什么需要那个......因为string
在这种情况下你既不能读取也不能写入值)
另请注意,test
这似乎不需要是通用的......您可以制作一个通用类型别名,例如:
type KeysAssignableFrom<T, V> = {
[K in keyof T]-?: V extends T[K] ? K : never
}[keyof T];
它将采用类型T
并V
返回T
其属性可从 分配的键V
。然后test()
变成:
function testConcrete(key: KeysAssignableFrom<Foo, string>) {}
这相当于:
// function testConcrete(key: "a" | "b" | "c"): void
好的,希望有帮助;祝你好运!
推荐阅读
- html - 带有容器文本和标题的背景图像
- highcharts - 我想添加一个加载微调器或添加一些对话框,直到加载 highcharts 并且在 react typescript 中加载图表后应该关闭?
- java - 物体越来越快,没有任何理由
- elasticsearch - Elasticsearch match_pharse 查询但提升文本前后没有任何单词的结果
- c# - 如何实现具有不同参数的一种方法。C#
- symfony - 使用 API 平台配置 Gedmo Abstract Personal Translatable
- node.js - 如何解密加密的文本
- raspberry-pi - 树莓派/boot/cmdline.txt的原始文件内容
- powershell - 在 PowerShell 中创建 HMAC SHA256 哈希
- php - Laravel - 在不多次查询数据库的情况下获取一列的总和