使用 TypeScript 定义类型的键作为 属性 类型

Use a TypeScript defined type's keys as a property type

抱歉,标题令人困惑。这是我的问题。

我有一个类型:

type Person = {
    firstName?: string;
    middleName?: string;
    lastName?: string;
}

假设我想动态获取这些属性之一。

const getPersonAttribute = (field: string) => {
    return person[field];
}

这会抛出 TS 错误(关于隐式类型 <string><any> 不能是类型 Person 的索引),所以为了让它工作,我正在这样做:

const getPersonAttribute = (field: 'firstName' | 'middleName' | 'lastName') => {
    return person[field];
}

有更好的方法吗?以某种方式动态获取类型的属性?

使用keyof你可以获得特定类型的钥匙。这是我将使用的语法(注意我使用函数而不是箭头函数以使其更具可读性):

function getPersonAttribute<K extends keyof Person>(field: K) {
    return person[field];
}

您只需要 keyof,如记录 here:

declare const person: Person;
const getPersonAttribute = (field: keyof Person) => {
  return person[field]; // okay
}
// const getPersonAttribute: (field: keyof Person) => string | undefined

在这种情况下,getPersonAttribute 的 return 类型是 string | undefined。如果您在 Person 中有不同类型的属性(例如 number 类型的 age),

type Person = {
  firstName?: string;
  middleName?: string;
  lastName?: string;
  age?: number;
}

那么 return 类型将是 stringnumberundefined 的并集,这对于您的用例可能不够具体:

// const getPersonAttribute: (field: keyof Person) => string | number | undefined
const personLastName = getPersonAttribute("lastName"); // string | number | undefined
const personAge = getPersonAttribute("age"); // string | number | undefined

如果你想让getPersonAttribute()的输出类型依赖于特定的输入键,那么你需要在输入中创建函数generic密钥类型:

const getPersonAttributeGen = <K extends keyof Person>(field: K) => {
  return person[field]; // okay
}
// const getPersonAttributeGen: 
// <K extends "firstName" | "middleName" | "lastName" | "age">(field: K) => Person[K]

这会产生类型 Person[K] 的输出,一种查找类型(记录在上面相同的 link 中):

const personLastNameBetter = getPersonAttributeGen("lastName"); // string | undefined
const personAgeBetter = getPersonAttributeGen("age"); // number | undefined

Playground link to code