打字稿:排除<t,k =“”>不排除我的类型

时间:2019-03-17 07:02:47

标签: typescript generics

我构建了一个名为compact的函数,该函数的作用是删除数组中的所有虚假值。

这是javascript的{​​{1}}实现:

compact

这是function compact(arr) { return arr.filter(Boolean); } const MyData = [0, 1, null, 2, undefined, '']; console.log(compact(MyData)) // => [1, 2] 的{​​{1}} 键入部分

Typescript

enter image description here

现在,这是古怪的部分,当我使用compact代码将其连接时,它实际上无法正常工作:

type Falsy = false | null | 0 | '' | undefined;

type Compact<T extends any[]> = Exclude<T[number], Falsy>;

// some correct test
type MyData = [0, 1, null, 2, undefined, ''];

type MyDataWithoutFalsy = Compact<MyData>
// => type MyDataWithoutFalsy = 1 | 2

它只能是compact,因为应该排除空字符串。

enter image description here

1 个答案:

答案 0 :(得分:4)

问题不是Exclude的问题,问题在于""(不仅是此字符串文字,对于任何字符串文字),打字稿通常不会保留字符串文字类型,但它将除非我们给出保留字面量类型的理由,否则应将其扩展为string

要向编译器提示您想要文字类型,必须将文字分配给受限于文字基本类型的通用类型参数:

function compact<V extends (string | undefined | boolean | object | number | null), T extends V[]>(arr: T & V[]): Compact<T> {
    return arr.filter(Boolean) as Compact<T>;
}

let MyDataWithoutFalsy = compact([0, 1, null, 2, undefined, '']); // number


type Falsy = false | null | 0 | '' | undefined;

type Compact<T extends any[]> = Exclude<T[number], Falsy>;

请注意,这确实意味着compact才真正可用,除非您以保留文字类型(例如'')的方式构造数组。

function compact<V extends (string | undefined | boolean | object | number | null), T extends V[]>(arr: T & V[]): Compact<T> {
    return arr.filter(Boolean) as Compact<T>;
}
function literalArray<V extends (string | undefined | boolean | object | number | null)>(arr: V[]): V[] {
    return arr.filter(Boolean);
}
let arr = literalArray([0, 1, null, 2, undefined, ''])
let MyDataWithoutFalsy = compact(arr); // 1| 2 ... beacuse resons