关于TypeScript计算属性的澄清与已知+未知属性类型定义咨询
Hey there! Great question—let’s break this down step by step.
First, to answer your first question: Yes, using an index signature like { [key: string]: number } is absolutely idiomatic TypeScript—but only for specific scenarios. This pattern is perfect when you truly don’t know what property names will exist on an object, but you do know that every string key will map to a number value. For example, if you’re dealing with dynamic data from an API where the keys might vary, this is a clean way to enforce type safety for the values.
That said, the downside of this approach when you do have some known properties (like legs or age in your Tiger example) is that TypeScript won’t give you type checking or autocompletion for those known keys. If you accidentally write Tiger.legss instead of Tiger.legs, the compiler won’t flag it—since legss is just another valid string key.
Now, for your second question: There’s a better way to type objects with both known and unknown properties while keeping structure and type safety—using an intersection type (combining a fixed type with an index signature). Here’s how it works:
// Define known required properties first type KnownAnimalProps = { legs: number; age: number; }; // Combine with an index signature for unknown properties type Animal = KnownAnimalProps & { [key: string]: number }; // Now this works, and you get autocompletion for legs/age let Tiger: Animal = { legs: 4, age: 5, tail: 1, eyes: 2 };
This approach gives you the best of both worlds:
- Type checking and autocompletion for your known properties (typos like
Tiger.legsswill throw an error) - Flexibility to add any extra string-keyed properties with number values
A quick note: If your unknown properties might have values of different types, you can adjust the index signature to use a union type, like { [key: string]: number | string }—just make sure your known properties also fit within that union to avoid type conflicts.
If you ever find that you actually can list all possible properties (even if some are optional), you might want to use a union of literal keys with Record instead, like:
type AnimalKeys = 'legs' | 'age' | 'tail' | 'eyes'; type Animal = Record<AnimalKeys, number>;
But this only works when you know all possible keys upfront—so it’s not ideal for truly unknown properties.
Hope this clears things up and gives you the tools to type your objects more precisely!
备注:内容来源于stack exchange,提问作者Reema

