给定一个类型,定义一个带有该类型参数键的函数联合

Given a type define a union of functions with parameters keys of the type

我有以下类型,我必须使用联合类型参数定义 formatter

declare type TableHeadCell<T> = {
    key: keyof T;
    label: string;
    formatter?: (cell: T[keyof T], row?: T) => string;
};

declare type Product = {
    article: string;
    quantity: number
};

const myTHeadCell: TableHeadCell<Product> = {
   key: 'article',
   label: 'Article',
   formatter(cell: string | number, row: Product): string { /* ... */ }
}

我需要的是一个联合函数类型,它允许我使用任一类型的参数定义函数。最好能缩小到key.

的类型
const myTHeadCell: TableHeadCell<Product> = {
   key: 'article',
   label: 'Article',
   formatter(cell: string, row: Product): string { /* ... */ }
}

// or

const myTHeadCell: TableHeadCell<Product> = {
   key: 'quantity',
   label: 'Article',
   formatter(cell: number, row: Product): string { /* ... */ }
};

此处进行的最简单方法是将 TableHeadCell<T> 设为 union 类型,keyof T 中每个 K 有一个成员。实现这一点的一种方法是制作一个映射类型,其中每个 属性 对应每个 K,然后获得这些属性的联合:

type TableHeadCell<T> = { [K in keyof T]: {
  key: K;
  label: string;
  formatter?: (cell: T[K], row?: T) => string;
} }[keyof T];

现在你可以无误地编写以下内容了:

const myTHeadCell1: TableHeadCell<Product> = {
  key: 'article',
  label: 'Article',
  formatter(cell: string, row?: Product): string { return "" }
}

const myTHeadCell2: TableHeadCell<Product> = {
  key: 'quantity',
  label: 'Article',
  formatter(cell: number, row?: Product): string { return "" }
};

编译器甚至会记住 myTHeadCell1.formatter() 接受一个 string 参数,而 myTHeadCell2.formatter() 接受一个 number 因为 control flow type analysis 会暂时缩小类型基于赋值的联合类型值:

if (myTHeadCell1.formatter) {
  myTHeadCell1.formatter(""); // okay
  myTHeadCell1.formatter(123); // error
}
if (myTHeadCell2.formatter) {
  myTHeadCell2.formatter(""); // error
  myTHeadCell2.formatter(123); // okay
}

请注意,我更改了格式化程序实现,因此 row 是可选的。这是匹配 TableHeadCell<T> 的定义所必需的。如果你希望 row 参数在实现中是必需的,它需要在注释类型中是必需的,因为你应该被允许根据定义用一个参数调用 TableHeadCell<T>.formatter!() 。 (确保您了解具有可选参数的函数类型与忽略额外参数的函数实现之间的区别,如 in the TypeScript FAQ 所述)。

好的,希望对您有所帮助;祝你好运!

Playground link to code