Typescript“Pick”意外允许任何属性值
下面是一个使用TS4.1.3编译的简单类型I:Typescript“Pick”意外允许任何属性值,typescript,Typescript,下面是一个使用TS4.1.3编译的简单类型I: interface Foo { [key: string]: any; bar: 'baz'; } 这应该允许对任何属性使用任何值,除了条,它仅限于一个值。例如,我不能执行const x:Foo={bar:'asdfadsf'}。这正是我所期望的 然后我会这样做: type Bar = Pick<Foo, string>; 类型栏=拾取; 除非我误解了Pick的工作原理,否则这应该是不可操作的,因为所有键都在str
interface Foo {
[key: string]: any;
bar: 'baz';
}
这应该允许对任何属性使用任何值,除了条
,它仅限于一个值。例如,我不能执行const x:Foo={bar:'asdfadsf'}
。这正是我所期望的
然后我会这样做:
type Bar = Pick<Foo, string>;
类型栏=拾取;
除非我误解了Pick
的工作原理,否则这应该是不可操作的,因为所有键都在string
中,包括bar
然而,令我惊讶的是const x:Bar={Bar:'asdfadsf'}
确实编译了
仅当我将Bar
的定义更改为Pick时代码>它是否成为真正的禁止操作
我哪里做错了
旁白:显然这是一个MWE,实际场景涉及React和其他第三方库,最终我可以强制执行正确的类型签名,我只想学习。为了理解这一点,您必须查看拾取的定义以及它一步一步地做什么
这是typescript在幕后应用的类型:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
Foo[string]
是any
,即使Foo['bar']
是baz
。
这里只有一个签名,因此它被简化为基本的字符串索引签名:
type Bar = {
[x: string]: any;
}
当您将其更改为Pick
时,它与Pick
相同。这不再与字符串索引签名匹配,因此您得到的类型仅包括定义的键bar
:
type Bar = {
bar: 'baz';
}
也许最真实的禁止操作是分别选择两个签名并将它们组合起来:
type Bar = Pick<Foo, 'bar'> & Pick<Foo, string>;
我想我明白了,谢谢。
type Bar = {
bar: 'baz';
}
type Bar = Pick<Foo, 'bar'> & Pick<Foo, string>;
type Bar = {
bar: 'baz';
} & {
[x: string]: any;
}