如果我在 TypeScript 中创建这个常量:
const PARAMS = {
green: {color: 0x007700},
black: {color: 0x000000},
white: {color: 0xffffff},
};
它将类型推导出为 { green: {color: number};黑色:{颜色:数字};白色:{颜色:数字}; }
.
但我从上下文中知道值的类型应该是 THREE.MeshBasicMaterialParameters
。我可以使用索引类型来声明它:
const PARAMS: {[name: string]: THREE.MeshBasicMaterialParameters} = {
green: {color: 0x007700},
black: {color: 0x000000},
white: {color: 0xffffff},
};
但随后我失去了键的特定可能性(“绿色”、“黑色”或“白色”)。我可以通过写出我想要的完整类型来更精确地建模:
const PARAMS: {
green: THREE.MeshBasicMaterialParameters,
black: THREE.MeshBasicMaterialParameters,
white: THREE.MeshBasicMaterialParameters
} = {
green: {color: 0x007700},
black: {color: 0x000000},
white: {color: 0xffffff},
};
但这非常冗长且重复。
有没有办法以更简洁的方式获取我想要的类型?
最佳答案
您可以通过使用通用映射类型来减少冗长
type ParamsType<Colors extends string> = {
[c in Colors]: THREE.MeshBasicMaterialParameters;
}
const PARAMS: ParamsType<'green' | 'black' | 'white'> = {
green: {color: 0x007700},
black: {color: 0x000000},
white: {color: 0xffffff},
};
但是你仍然需要重复颜色名称两次。如果你想让 typescript 推导 key ,你必须引入中间函数,在运行时完全没有用处。我不知道还有什么其他方法可以让 typescript 推断通用参数 - there is a proposal on github允许扣除默认模板参数,但到目前为止尚未实现任何内容。
function inferColorKeys<Colors extends string>(params: ParamsType<Colors>): ParamsType<Colors> {
return params;
}
const PARAMS = inferColorKeys({
green: {color: 0x007700},
black: {color: 0x000000},
white: {color: 0xffffff},
});
更新
您可以按照 @jcalz 的建议,通过创建 inferKeys
使其完全通用。进入一个接受显式泛型参数并返回一个推断其泛型参数的函数的函数。它必须是两个函数,因为一个函数不能有一些显式的通用参数和一些推断的参数。此外,它还利用内置的 Record
类型定义为
type Record<K extends string, V> = {[k in K]: V}
.
const inferKeys = <V>() => <K extends string>(x: Record<K,V>): Record<K,V> => x;
const PARAMS = inferKeys<THREE.MeshBasicMaterialParameters>()({
green: {color: 0x007700},
black: {color: 0x000000},
white: {color: 0xffffff},
});
PARAMS
的类型被推断为
Record<"green" | "black" | "white", THREE.MeshBasicMaterialParameters>
关于typescript - 我可以在 TypeScript 中指定值类型,但仍让 TS 推断出键类型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46100834/