【发布时间】:2020-03-11 21:15:09
【问题描述】:
尝试创建一个简单的表格组件,但在按我想要的方式工作时遇到了一些麻烦。
TL;DR 如何在这个Playground Link 中写入Column3 的类型,以便消除2 个错误?
这行得通
所以给出以下常见的东西:
type Data = { id: number, name: string };
const data: Data[] = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
]
type Header = { header: string };
这是一个变体,可让您提供类型安全的字段名称,并可选择为该字段的值提供格式化函数:
type Value1<Row> = {
[Key in keyof Row]: {
field: Key;
format?: (value: Row[Key]) => string;
};
}[keyof Row];
type Column1<Row> = Header & Value1<Row>;
const makeTable = <R>(r: R[], c: Column1<R>[]) => {}
makeTable(data, [
{ header: 'Id', field: 'id' },
{ header: 'Name', field: 'name', format: value => value.toUpperCase() },
])
这里有一个变体,它让你只提供一个格式化函数,而不是一个值你得到行对象:
type Value2<Row> = {
format: (row: Row) => string;
};
type Column2<Row> = Header & Value2<Row>;
const makeTable = <R>(r: R[], c: Column2<R>[]) => {};
makeTable(data, [
{ header: 'Id', format: row => row.id.toString() },
{ header: 'Name', format: row => row.name.toUpperCase() },
])
这不是...
当我想结合这两个时,问题就出现了,因为对于某些列,第一个变体有意义,而对于其他列,第二个变体有意义。
我想我可以这样做,但 Typescript 不高兴......
type Column3<Row> = Header & (Value1<Row> | Value2<Row>); // <-- Non-working discriminated union?
const makeTable = <R>(r: R[], c: Column3<R>[]) => { };
makeTable(data, [
{ header: 'Id', field: 'id' },
{ header: 'Name', field: 'name', format: value => value.toUpperCase() },
{ header: 'Test', format: row => `${row.id} : ${row.name}` },
])
显然data 的类型现在不正确,而且由于某种原因,第三列中的row 隐含为any,当然不应该这样。
我可以通过明确说明通用 Row 类型来“修复”data 的类型:
makeTable<Data>(data, [
{ header: 'Id', field: 'id' },
{ header: 'Name', field: 'name', format: value => value.toUpperCase() },
{ header: 'Test', format: row => `${row.id} : ${row.name}` },
])
但是row 仍然是隐含的any,而且这里真的没有必要显式,所以这里肯定有什么不妥……但是……我不明白这里发生了什么. ????
我在这里误会了什么?
【问题讨论】:
标签: typescript