ts数据类型之never的妙用

714 阅读2分钟

never是兜底类型, 表示不可达

typescript的 never 类型代表永不存在的值的类型,它只能被赋值为 never

任意类型与 never 交叉都得到 never

type A = 'A';
type B = 'B';
type C = A & B; // 此时C 的类型为never
// 联合类型 C 是类型 A 和类型 B 的交集,这意味着其类型值同时等于 A 和 B。这种类型定义叫做联合类型,在 TypeScript 中是支持的,但是该例子的写法表示类型 C 的值同时等于 A 和 B,显然这是不可能达到的条件,所以这里类型 C 就是 never 类型。
type T1 = number & never; // never 
​
type T2 = string & never; // never

作用1 :

type methods = 'get' | 'post'
function getSomething(methods: methods) {
    switch (methods) {
        case 'get':
            console.log('get');
            return methods  // 此时methods 自动推断为get
        case 'post':
            console.log('post');
            return methods  // 此时methods 自动推断为post
        default:
            console.log('never');
            return methods  // 此时methods 自动推断为never
    }
}

当我们在开发过程中, 如果要给methods 追加 'put' 类型的话, 那么default的 methods 就会被自动推断为 put,那么这个时候 如果我们忘记给 switch 添加 put 分支 , 程序也不报错, 这显然不是我们想要的结果

这时候, 我们可以利用 兜底类型, never

type methods = 'get' | 'post'
function getSomething(methods: methods) {
    switch (methods) {
        case 'get':
            console.log('get');
            return methods
        case 'post':
            console.log('post');
            return methods
        default:
                const nev:never = methods   // 声明一个never类型, 用于接收ts类型收缩最后得到的methods:never
            console.log("never");
            return nev
    }
}

此时, 我们声明一个变量 nev , 标注他的类型为 never 类型, 只有 never类型才能给never类型赋值

那么如果我们给 methods添加一个类型 ' put ' 此时就会报错, 说 string 类型不能赋值给 never类型, 这也 提醒我们 添加完对应的 'put' 类型之后, 需要添加对应的 methods 为 put 的逻辑。 这有益于维护我们的代码

type methods = 'get' | 'post' | 'put'
function getSomething(methods: methods) {
    switch (methods) {
        case 'get':
            console.log('get');
            return methods
        case 'post':
            console.log('post');
            return methods
        default:
            const nev:never = methods  // 此时ts类型推断 methods 的值为 'put' , string不能赋值给never
            console.log("never");
            return nev
    }
}

image.png

作用2: 剔除某一类型

如果我们要定义一个类型, 这个类型是除了Date类型之外的所有类型 我们兴许可以这么写

function fn1(x){
    if(x instanceof Date){
        throw Error('123')
    }
}

但是, 这个这样的ts 未免有点js

此时,我们可以利用ts的never类型解决问题

function fn<T>(x:T extends Date ? never : T){
    console.log(x);
}

我们接收一个泛型T, 如果这个类型继承了 Date类型, 那么就返回一个never类型,否则我们就返回原来的类型

image.png