我有以下代码:
interface DummyTableRow {
id: number;
name: string;
}
interface RowChange<Row extends object> {
newRow: Row | null;
oldRow: Row | null;
}
interface RowChangeBag {
Dummy: RowChangeList<DummyTableRow>;
}
type RowChangeList<Row extends object> = Array<RowChange<Row>>;
function add<
Row extends object,
T extends keyof RowChangeBag,
// error on next line: Type 'DummyTableRow' is not assignable to type 'Row'.
L extends RowChangeList<Row> = RowChangeBag[T]
>(
bag: RowChangeBag,
tableName: T,
newRow: Row | null,
oldRow: Row | null,
) {
bag[tableName].push({ newRow, oldRow });
}
为什么抱怨?为什么DummyTableRow
无法分配给Row
?
或者这可能是一个&#39; bug&#39;打字稿? (我在本例中使用的是2.6.2版本)
答案 0 :(得分:2)
这不是TypeScript错误。
您看到的行为可以简化为以下内容:
interface DummyTableRow {
id: number;
name: string;
}
function doing<Row>() {
let a: DummyTableRow
let b: Row
// error on next line: Type 'DummyTableRow' is not assignable to type 'Row'.
b = a
}
这里的问题是,由于Row
是泛型类型,编译器无法判断a
是否可以分配给b
,因为b
可以是使用时定义的任何类型,例如
doing<{ a: string }>()
答案 1 :(得分:1)
您的代码混合了两种名称相似但类型不兼容的类型:
DummyTableRow
是你对行的抽象→确定Row extends object
:object
与DummyTableRow
不兼容:id
和name
属性缺失。 →只需Row extends DummyTableRow
。其他问题:
RowChangeBag
也必须是通用的。RowChangeBag
旨在存储多个RowChangeList
,参见T extends keyof RowChangeBag
和bag[tableName]
是RowChangeList
。在下面的代码中,我将它拆分为2个接口,这样就可以更容易地在其中添加表格。L
方法中的add
泛型类型约束。我建议增强代码可读性:
T
开头的通用类型名称:Row
→TRow
DummyTableRow
名称可以简化:仅Row
null
;仅使用undefined
。T[]
而不是Array<T>
,因为它更短,更适合JavaScript。修正提案(在TypeScript Playground上测试):
interface Row {
id: number;
name: string;
}
interface RowChange<TRow extends Row> {
newRow?: TRow;
oldRow?: TRow;
}
type RowChangeList<TRow extends Row> = RowChange<TRow>[];
interface TableGroup<T> {
Table1: T;
Table2: T;
}
interface RowChangeBag<TRow extends Row>
extends TableGroup<RowChangeList<TRow>> { }
function add<
TRow extends Row,
TKey extends keyof RowChangeBag<TRow>
>(
bag: RowChangeBag<TRow>,
tableName: TKey,
newRow: TRow,
oldRow: TRow,
) {
bag[tableName].push({ newRow, oldRow });
}