英文:
How can I keep the original index signature of an object, but still specify the type of its values?
问题
我有一个具有字符串键和类型化值的大对象。我想为这个对象添加类型。
interface Animal {
legs: 0 | 1 | 2 | 3 | 4;
}
const Animals: Record<string, Animal> = {
snake: { legs: 0 },
dog: { legs: 4 },
bird: { legs: 2},
// 更多条目...
};
如果我将对象类型化为Record<string, Animal>
,那么所有字符串都变成有效的键。因此,没有防止我意外地写入Animals.birb
的保护措施。像Record<"snake" | "dog" | "bird" ... , Animal>
这样做是愚蠢的,因为对象很大且具有许多键。
如果我不显式编写类型定义,TypeScript将推断类型为{ snake: { legs: number}, dog: { legs: number}, ... }
。
这是不好的,因为我需要TypeScript知道值的类型是Animal
,而不仅仅是{ legs: number }
,
即类型应该是{ snake: Animal, dog: Animal, ... }
。
为每一行编写as Animal
是愚蠢的。
有没有更好的方法来为这个对象添加类型?
英文:
I have a large object with string keys and typed values. I want to type this object.
interface Animal {
legs: 0 | 1 | 2 | 3 | 4;
}
const Animals: Record<string, Animal> = {
snake: { legs: 0 },
dog: { legs: 4 },
bird: { legs: 2},
// many more entries...
};
If I type the object as Record<string, Animal>, then all strings become valid keys. So there is no protection against me accidentally writing Animals.birb
. It would be silly to do something like Record<"snake" | "dog" | "bird" ... , Animal>
because the object is big and has many keys.
If I do not explicitly write a type definition, then TypeScript will infer the type as
{ snake: { legs: number}, dog: { legs: number}, ... }
.
This is bad because I need TypeScript to know that the type of value is Animal
and not just { legs: number }
,
i.e., the type should be { snake: Animal, dog: Animal, ... }
Writing as Animal
for every line would be silly.
Is there a better way to type this object?
答案1
得分: 1
以下是您要翻译的代码部分:
如果您想要确保变量可以分配给一种类型而不标注为该类型,并且潜在地丢失信息(比如特定的键),您可以使用满足运算符 satisfies
:
const Animals = {
snake: { legs: 0 },
dog: { legs: 4 },
bird: { legs: 2 },
} satisfies Record<string, Animal>;
/* const Animals: {
snake: {
legs: 0;
};
dog: {
legs: 4;
};
bird: {
legs: 2;
};
} */
您可以看到 Animals
已被推断出具有已知的键,以及其 legs
属性的适当狭义文字类型,而不是原本推断的较宽泛的 number
类型。
这也会捕获初始化器中的错误,类似于标注:
const badAnimals = {
snake: { legs: 0 },
dog: { legs: 4 },
bird: { legs: 2 },
octopus: { legs: 8 } // 错误!
} satisfies Record<string, Animal>;
英文:
If you want to ensure that a variable is assignable to a type without annotating it as that type and potentially throwing away information (like the particular keys), you can use the satisfies
operator:
const Animals = {
snake: { legs: 0 },
dog: { legs: 4 },
bird: { legs: 2 },
} satisfies Record<string, Animal>;
/* const Animals: {
snake: {
legs: 0;
};
dog: {
legs: 4;
};
bird: {
legs: 2;
};
} */
You can see that Animals
has been inferred with known keys, and with properties whose legs
are of appropriately narrow literal types instead of the wider number
type which would have been inferred otherwise.
This also will catch mistakes in your initializer similarly to an annotation:
const badAnimals = {
snake: { legs: 0 },
dog: { legs: 4 },
bird: { legs: 2 },
octopus: { legs: 8 } // error!
} satisfies Record<string, Animal>;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论