问题描述
我正在尝试做类似的事情:
type Sizes = 'small' | 'large';
const CONfig_BY_SIZE: Record<Sizes,any> = {
small: {
a: ...,b: ...,c: ...,},large: {
a: ...,}
它有效,但是当我尝试输入 CONfig_BY_SIZE.large.
时,a
或 b
或 c
没有自动完成。我认为这是因为我将值定义为任何。
值本身很大,所以如果可能的话,我更喜欢它自动生成。
我的目标是将键定义为 Sizes
但我仍然可以自动完成该值。
我如何实现这一目标?
谢谢!
解决方法
如果您想应用某种类型约束,但从值中推断出比该约束更具体的内容,那么这就是函数的泛型参数所做的。
所以我认为您需要提供一个函数来允许打字稿进行推断:
function createConfigBySize<T extends Record<Sizes,unknown>>(config: T): T {
return config
}
这样做是将 T
映射到 extends Record<Sizes,unknown>
。 Typescript 准确记录了它是什么子类型,并将其保存到 T
。然后将返回类型设置为 T
以获取推断的任何内容。
现在你可以这样做:
const CONFIG_BY_SIZE = createConfigBySize({
small: {
a: 123,b: 'abc',c: false,},large: {
a: { cool: true },b: null,c: [1,2,3],})
产生这种类型的:
{
small: {
a: number;
b: string;
c: boolean;
};
large: {
a: {
cool: boolean;
};
b: null;
c: number[];
};
}
如果您使用无效的大小键,您仍然可以进行类型检查:
createConfigBySize({
small: { foo: 123 },medium: { bar: 123 },// type error
})
也就是说,如果您希望 small.a
与 large.a
的类型相同,这不是正确的解决方案。在这种情况下,您确实应该为任何类型创建一个接口。如果您需要在多个地方重用一个类型,那么正式声明该接口是一个非常好的主意。
您可以使用类似的语法来强制对象具有联合类型中每个条目的键:
type Sizes = 'small' | 'large';
type Keys = 'a' | 'b' | 'c';
const CONFIG_BY_SIZE: Record<Sizes,{ [key in Keys]: any }> = {
small: {
a: 1,b: 2,c: 2,large: {
a: 2,}
您也可以将其设为泛型。
代码示例 here。