我正在尝试解决代码:
type Wrap<T> = {
value: T
}
function wrapIt<T>(t: T): Wrap<T> {
return { value: t}
}
const arr: Array<string|number> = ["a", 1]
const arr2: Array<Wrap<string|number>> = arr.map(wrapIt)
const arr3: Array<Wrap<string>|Wrap<number>> = arr.map(wrapIt) // <--- Doesn't compile
编译器说:
Type 'Wrap<string | number>[]' is not assignable to type '(Wrap<string> | Wrap<number>)[]'.
Type 'Wrap<string | number>' is not assignable to type 'Wrap<string> | Wrap<number>'.
Type 'Wrap<string | number>' is not assignable to type 'Wrap<string>'.
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
arr3
是我与其他一些我不拥有的代码兼容所需要的。此外,从概念上讲,它似乎更正确。
有没有一些打字黑魔法可以让它按照我想要的方式运行?现在,我将使用as
键入强制转换。
编辑:Array<string|number>
只是一个例子,我经常使用这种模式,所以我希望解决方案适用于Array<T>
,其中T
是任意的,可以是像string|number
一样的并集,但不仅仅是。
您可以在返回类型时更改函数的定义,使其分布在T
上。因此,这意味着当映射并集(如number | string
(时,您将为每个并集组成部分(因此为Wrapped<number> | Wrapped<string>
(获得Wrapped
的实例化的并集,而不是为并集(因此不是Wrapped<string | number>
(获得Wrapped
的实例化
type DistraibutiveWrapped<T> = T extends T ? Wrap<T> : never
function wrapIt<T>(t: T): DistraibutiveWrapped<T> {
return { value: t} as DistraibutiveWrapped<T>
}
游乐场链接
是否使用显式类型检查?
type Wrap<T> = {
value: T
}
function wrapIt<T>(t: T): Wrap<T> {
return { value: t }
}
const arr: Array<string | number> = ["a", 1]
const arr2: Array<Wrap<string | number>> = arr.map(wrapIt)
const arr3: Array<Wrap<string> | Wrap<number>> = arr.map(x => {
switch (typeof x) {
case 'string':
return wrapIt<string>(x);
case 'number':
return wrapIt<number>(x);
default:
return wrapIt(x);
}
});
您可以创建额外的函数并重载它:
type Wrap<T> = {
value: T
}
function wrapIt<T>(t: T): Wrap<T> {
return { value: t }
}
const arr: Array<string | number> = ["a", 1]
function map<Item,>(arr: Item[]): Array<Wrap<string> | Wrap<number>>
function map<Item,>(arr: Item[]) {
return arr.map(wrapIt)
}
// (Wrap<string> | Wrap<number>)[] which is equivalent to Array<Wrap<string> | Wrap<number>>, just different syntax
const result = map(['hello', 42])
游乐场