如何指定 Typescript 泛型 T[K] 是数字类型?
How can I specify that Typescript generic T[K] is number type?
我有一个像这样的简单 Typescript 函数:
function getProperty<T, K extends keyof T>(obj: T, key: K): number {
return obj[key]; // This line is not compiling.
// Typescript will yell: "Type 'T[K]' is not assignable to type 'number'."
}
我的用法是这样的:
const someObj = {
myValue: 123,
otherProperty: '321'
}
getProperty(someObj, 'myValue')
我不知道someObj
的结构是什么。
我的问题是:如何静态指定T[K]
是数字类型?
I won't know what structure of someObj
will be.
那么 TypeScript 真的帮不了你。 TypeScript 的类型检查在 编译时 完成。如果 someObj
的结构仅在 运行时 才知道,TypeScript 无法对该结构进行类型安全访问。您需要在编译时知道 属性 键和这些属性的可能值是什么。
例如:在您的示例中,属性 名称是字符串,属性 值是字符串或数字(但不是布尔值或对象等)。您可以声明一个由字符串索引的类型(因为所有 属性 名称最终都是字符串或符号,在本例中为字符串),其中 属性 值是数字或字符串:
declare type SomeObjType = {
[key: string]: number | string
};
然后getProperty
是:
function getProperty<T extends SomeObjType>(obj: T, key: string): number | string {
return obj[key];
}
你可以像这样使用它(在这种情况下,我使用 JSON.parse
来模拟从程序范围之外接收此数据):
const someObj: SomeObjType = JSON.parse(`{
"myValue": 123,
"otherProperty": "321"
}`);
console.log(getProperty(someObj, 'myValue'));
console.log(getProperty(someObj, 'otherProperty'));
但这并没有给你带来太多好处,并且排除了 属性 值不是数字或字符串的可能性。
您可能只需要使用 object
:
function getProperty(obj: object, key: string) {
return obj[key];
}
const someObj = JSON.parse(`{
"myValue": 123,
"otherProperty": "321"
}`);
console.log(getProperty(someObj, 'myValue'));
console.log(getProperty(someObj, 'otherProperty'));
如果您正在处理的对象的类型足以让打字稿知道它们的形状,那么您完全可以这样做[typescript playgrounds link,如果您想做一些实验的话。
您只需缩小哪些标识符 key
可以是 number
类型 属性:
的引用之一
const someObj = {
myValue: 123,
otherProperty: '321'
};
getProperty(someObj, 'myValue'); // works
getProperty(someObj, 'otherProperty'); // wails
function getProperty<T, K extends NumericProps<T>>(obj: T, key: K): number {
return obj[key];
}
type NumericProps<T> = {
[K in keyof T]: T[K] extends number ? K : never
}[keyof T];
我有一个像这样的简单 Typescript 函数:
function getProperty<T, K extends keyof T>(obj: T, key: K): number {
return obj[key]; // This line is not compiling.
// Typescript will yell: "Type 'T[K]' is not assignable to type 'number'."
}
我的用法是这样的:
const someObj = {
myValue: 123,
otherProperty: '321'
}
getProperty(someObj, 'myValue')
我不知道someObj
的结构是什么。
我的问题是:如何静态指定T[K]
是数字类型?
I won't know what structure of
someObj
will be.
那么 TypeScript 真的帮不了你。 TypeScript 的类型检查在 编译时 完成。如果 someObj
的结构仅在 运行时 才知道,TypeScript 无法对该结构进行类型安全访问。您需要在编译时知道 属性 键和这些属性的可能值是什么。
例如:在您的示例中,属性 名称是字符串,属性 值是字符串或数字(但不是布尔值或对象等)。您可以声明一个由字符串索引的类型(因为所有 属性 名称最终都是字符串或符号,在本例中为字符串),其中 属性 值是数字或字符串:
declare type SomeObjType = {
[key: string]: number | string
};
然后getProperty
是:
function getProperty<T extends SomeObjType>(obj: T, key: string): number | string {
return obj[key];
}
你可以像这样使用它(在这种情况下,我使用 JSON.parse
来模拟从程序范围之外接收此数据):
const someObj: SomeObjType = JSON.parse(`{
"myValue": 123,
"otherProperty": "321"
}`);
console.log(getProperty(someObj, 'myValue'));
console.log(getProperty(someObj, 'otherProperty'));
但这并没有给你带来太多好处,并且排除了 属性 值不是数字或字符串的可能性。
您可能只需要使用 object
:
function getProperty(obj: object, key: string) {
return obj[key];
}
const someObj = JSON.parse(`{
"myValue": 123,
"otherProperty": "321"
}`);
console.log(getProperty(someObj, 'myValue'));
console.log(getProperty(someObj, 'otherProperty'));
如果您正在处理的对象的类型足以让打字稿知道它们的形状,那么您完全可以这样做[typescript playgrounds link,如果您想做一些实验的话。
您只需缩小哪些标识符 key
可以是 number
类型 属性:
const someObj = {
myValue: 123,
otherProperty: '321'
};
getProperty(someObj, 'myValue'); // works
getProperty(someObj, 'otherProperty'); // wails
function getProperty<T, K extends NumericProps<T>>(obj: T, key: K): number {
return obj[key];
}
type NumericProps<T> = {
[K in keyof T]: T[K] extends number ? K : never
}[keyof T];