这就很奇怪, { [key: string]: unknown } 本身就为 T 的约束, 用 { [key: string]: unknown } 和用 T 有什么区别吗?
在我一顿 Google 之后, 在一篇文章中明白了其中道理.
理解 TS 报错信息
下面我将分解错误消息的每句话:
1 2
Type '{}' is not assignable to type 'T'. '{}' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{ [key: string]: unknown; }'
Type '{}' 什么意思?
这个类型可以分配任何值,除了 null 或 undefined。例如:
1 2 3 4 5 6 7
type A = {}; consta0: A = undefined; // error consta1: A = null; // error consta2: A = 2; // ok consta3: A = "hello world"; //ok consta4: A = { foo: "bar" }; //ok // and so on...
is not assignable 什么意思?
分配是实例与类型相匹配。如果你的实例不匹配类型,你会得到一个错误。例如:
1 2 3 4 5
// type string is not assignable to type number consta: number = "hello world"; //error
// type number is assinable to type number constb: number = 2; // ok
a different subtype 什么意思?
A 是 S 的子类型: 类型 A 在类型 S 的基础上增加了额外属性.
A 和 B 是 S 的不同子类型: 类型 A 与类型 B 分别在类型 S 的基础上增加了不同的额外属性.
例如: 下面代码的情况是
A 和 D 是相同的类型
B 是 A 的子类型
E 不是 A 的子类型
B 和 C 是 A 的不同子类型
1 2 3 4 5
type A = { readonly0: "0" }; type B = { readonly0: "0"; readonlyfoo: "foo" }; type C = { readonly0: "0"; readonlybar: "bar" }; type D = { readonly0: "0" }; type E = { readonly1: "1"; readonlybar: "bar" };
1 2 3 4 5
type A = number; type B = 2; type C = 7; type D = number; type E = `hello world`;
1 2 3 4 5
type A = boolean; type B = true; type C = false; type D = boolean; type E = number;
当你在 ts 中使用 type 关键字时, 例如: type A = { foo: 'Bar' }, 那么 A 指向的是该值的结构.
const func = <A extendsFoo>(a: A = foo_SubType) =>`hello!`; //error!
产生如下错误信息:
1 2
Type 'SubType' is not assignable to type 'A'. 'SubType' is assignable to the constraint of type 'A', but 'A' could be instantiated with a different subtype of constraint 'Foo'.ts(2322)
const c0 = func(foo); // ok! type 'Foo' will be infered and assigned to 'A' const c1 = func(foo_SubType); // ok! type 'SubType' will be infered const c2 = func(foo_DiffSubType); // ok! type 'DiffSubType' will be infered