3

我有一个简单的 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]静态指定数字类型?

4

2 回答 2

2

如果您正在使用的对象的类型足以让 typescript 知道它们的形状,那么您完全可以这样做 [ 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];
于 2021-06-15T03:29:04.287 回答
1

我不知道someObj将是什么结构。

那么 TypeScript 并不能真正帮你解决这个问题。TypeScript 的类型检查在compile-time完成。如果 的结构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'));

在操场上

于 2019-03-08T09:53:19.990 回答