从TypeScript中的类型T返回单个属性的类型

9udxz4iz  于 2023-02-05  发布在  TypeScript
关注(0)|答案(1)|浏览(136)

我有一个从JavaScript移植的helper函数:

function extractDistinct(data, fieldName) {
  const uniques = data.reduce(
    (set, x) => set.add(x[fieldName]), new Set()
  );
  return [...uniques];
}

这个函数简化了从一个数组中提取fieldName属性的唯一值列表。虽然JavaScript代码实际上允许不同数据类型的集合--只要它们有想要的字段--我想我尝试获得的TypeScript版本将限制为单一类型的数组。
以下是我目前掌握的情况:

function extractDistinct<T>(data: T[], fieldName: keyof T): unknown[] {
  const uniques = data.reduce((set, x) => set.add(x[fieldName]), new Set());
  return [...uniques];
}

它的工作原理是TS编译器正在检查以确保fieldName确实是T的属性,但我必须将整个内容转换为预期类型,这有点笨拙:

const people: Person[] = .... // doesn't matter where it comes from.
const hairColor = extractDistinct(people, 'hair_color') as string[]);

我现在把它当作返回unknown[],但是我试图返回为这个键/字段声明的类型T,这怎么能实现呢?

js5cn81o

js5cn81o1#

您希望extractDistinct()fieldName参数的字符串文字类型K以及data的元素类型T中为generic,其中K被约束为keyof T

function extractDistinct<T, K extends keyof T>(data: T[], fieldName: K): T[K][] {
  const uniques = data.reduce((set, x) => set.add(x[fieldName]), new Set<T[K]>());
  return [...uniques];
}

这个函数使用indexed access typeT[K]来表示TK键处的属性类型,编译时没有出现错误,现在你得到了想要的行为:

interface Person {
  hair_color: string;
  number_of_limbs: number;
  actually_three_hedgehogs_in_a_trenchcoat: boolean;
}
declare const people: Person[];

const hairColor = extractDistinct(people, 'hair_color');
// const hairColor: string[]

const numberOfLimbs = extractDistinct(people, 'number_of_limbs');
// const numberOfLimbs: number[]

Playground代码链接

相关问题