如何在此代码中定义MyInterfaceKeys
?
interface MyInterface extends Record<string, any> {
Appearance?: "default" | "primary" | "link";
Size?: "small" | "medium" | "large";
Color?: string;
Block?: boolean;
}
type MyInterfaceKeys = (keyof MyInterface)[]
// ok => MyInterfaceKeys === ["Block", "Color"]
// ok => MyInterfaceKeys === ["Appearance"]
// Error => MyInterfaceKeys === ["UnknownKey"]
事实上,我想将对象道具转换为联合文字:
type MyInterfaceKeys = ("Appearance" | "Size" | "Color" | "Block")[]
TypeScript中的对象类型有一组已知键,这些键对应于单个字符串或数字文本(或符号);和一组索引签名密钥,它们同时对应于多个可能的密钥(这些密钥过去只是string
或number
,但现在您也可以在索引签名中使用模式模板文字和符号)。例如,以下类型:
type Foo = {
[k: string]: 0 | 1
x: 0,
y: 1
}
具有两个已知密钥CCD_ 4和CCD_。您的MyInterface
类型有四个已知密钥,但它也有一个string
索引签名密钥(因为它扩展了具有string
索引签名密钥的Record<string, any>
)。
keyof
运算符生成所有键的并集。对于Foo
,也就是"x" | "y" | string
,对于MyInterface
,也就是说"Appearance" | "Size" | "Color" | "Block" | string
。
由于每个字符串文字(如"x"
和"y"
)都是string
的一个子类型,因此字符串文字类型与string
的并集仅为string
,编译器急切地将其简化为CCD_18。所以CCD_ 21和CCD_。在某种意义上,CCD_;吸收";所有字符串文字键。
因此,如果有任何索引签名密钥吸收了keyof
,则不能使用CCD_25仅获取已知密钥
那么,你能做什么?你能做的最干净的事情就是考虑重构你的代码,这样你想要的信息就可以更容易地被捕获:
interface MyKnownInterface {
Appearance?: "default" | "primary" | "link";
Size?: "small" | "medium" | "large";
Color?: string;
Block?: boolean;
}
interface MyInterface extends Record<string, any>, MyKnownInterface { }
type KK = (keyof MyKnownInterface) & string
// type KK = "Appearance" | "Size" | "Color" | "Block"
type MyInterfaceKeys = (keyof MyKnownInterface)[]
// type MyInterfaceKeys = (keyof MyKnownInterface)[]
// type MyInterfaceKeys = ("Appearance" | "Size" | "Color" | "Block")[]
这里的MyInterface
与以前相当,但keyof MyKnownInterface
是您想要的已知密钥的并集。
您也可以使用类型操作来尝试梳理出已知的键,而不是仅使用keyof
,尽管我认为我所知道的所有可能的方法都有一些奇怪的边缘情况(我即将提交一个与symbol
键有关的错误)。但希望您不会遇到这种边缘情况(MyInterface
示例没有)。
一种方法是在映射类型中使用密钥重映射来抑制索引签名,索引签名可以被识别为任何不需要值的密钥,即使它不是可选的(索引签名表示任何数量的正确类型的密钥,包括零个这样的密钥):
type KnownKeys<T> = keyof {
[K in keyof T as {} extends { [P in K]: any } ? never : K]: never
}
如果我们在你的情况下这样做,你会得到:
type MyInterfaceKeys = (KnownKeys<MyInterface>)[]
// type MyInterfaceKeys = ("Appearance" | "Size" | "Color" | "Block")[]
游乐场链接到代码