提问人:taffec 提问时间:11/13/2023 最后编辑:taffec 更新时间:11/13/2023 访问量:39
Typescript 是否允许 Map 具有不同的泛型?
Does Typescript allow Map to have different generics?
问:
我是 Typescript 的新手,并试图学习如何创建一个具有类型属性的类,其中 .我在为它编写构造函数时遇到了麻烦,因为 Typescript 希望我声明什么是,即使我选择了 or .我也认为我会遇到麻烦,因为可能包含多个具有不同的数组。当传递到构造函数而不是方法时,它也会失败。Map<string, Val<T>>
type Val<T> = string | number | Array<T>
<T>
string
number
Map
T
我的代码看起来像这样
type Val<T> = string | number | Array<T>
这会引发错误
export class MyClass<T> {
model;
constructor(model: [string, Val<T>][]) {
this.model = new Map<string, Val<T>>(model);
}
}
const c = new MyClass([
["key1", "val1"],
["key2", 99],
["key3", ["cat", "dog"]],
["key4", [1,2,3]],
]);
src/fakefuse.ts:38:15 - error TS2322: Type 'number' is not assignable to type 'string'.
38 ["key4", [1,2,3]],
src/fakefuse.ts:38:17 - error TS2322: Type 'number' is not assignable to type 'string'.
38 ["key4", [1,2,3]],
src/fakefuse.ts:38:19 - error TS2322: Type 'number' is not assignable to type 'string'.
38 ["key4", [1,2,3]],
奇怪的是,出于某种原因,使用方法与构造函数进行编译时没有任何错误
class MyClass<T> {
model;
constructor() {
this.model = new Map<string, Val<T>>();
}
init(model: [string, Val<T>][]) {
this.model = new Map<string, Val<T>>(model);
}
}
const c = new MyClass();
c.init([
["key1", "val1"],
["key2", 99],
["key3", ["cat", "dog"]],
["key4", [1,2,3]],
]);
这似乎只有在将值直接传递给 !如果你尝试了一个变量,你会得到这个。c.init
const c = new MyClass();
const aVar = [
["key1", "val1"],
["key2", 99],
["key3", ["cat", "dog"]],
["key4", [1,2,3]],
];
c.init(aVar);
src/fakefuse.ts:45:8 - error TS2345: Argument of type '((string | number)[] | (string | string[])[] | (string | number[])[])[]' is not assignable to parameter of type '[string, Val<unknown>][]'.
Type '(string | number)[] | (string | string[])[] | (string | number[])[]' is not assignable to type '[string, Val<unknown>]'.
Type '(string | number)[]' is not assignable to type '[string, Val<unknown>]'.
Target requires 2 element(s) but source may have fewer.
45 c.init(aVar);
有人可以帮助我了解我应该如何做到这一点吗?我觉得也许这就是作用,但我真的不知道它是如何工作的?extends
答:
奇怪的是,出于某种原因,使用方法与构造函数进行编译时没有任何错误
那是因为当你这样做时
const c = new MyClass();
您不会将任何类传递给类型参数,使其成为 类型。MyClass<unknown>
因此,当你做之后
c.init(...);
它会接受任何东西,因为理论上任何东西都可以分配给 .unknown
为什么当你把它直接传递给构造函数时它不起作用?因为在创建对象时,如果你不传递任何类型参数,Typescript 会尝试从构造函数参数中推断:
const c = new MyClass([
["key1", "val1"],
["key2", 99],
["key3", ["cat", "dog"]],
["key4", [1,2,3]],
]);
对于列表中的每一项,Typescript 将尝试推断它们的类型:第一个元素是 a,第二个元素是 a,第三个元素是 .它在那里停顿并推断为 ,使 .string
number
Array<string>
T
string
c
MyClass<string>
它现在查看第四个元素 a ,并正确地抱怨,因为如果推断为 ,那么它必须只包含 s、s 或 s。Array<number>
T
string
string
number
Array<string>
为了不让它抱怨,你可以显式地将类的类型参数声明为 和 之间的并集:string
number
type Val<T> = string | number | Array<T>
export class MyClass<T> {
model;
constructor(model: [string, Val<T>][]) {
this.model = new Map<string, Val<T>>(model);
}
}
const c = new MyClass<string | number>([
["key1", "val1"],
["key2", 99],
["key3", ["cat", "dog"]],
["key4", [1,2,3]],
]);
评论
any
MyClass<any>
MyClass<string | number>
评论