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
}
}
作用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类型,否则我们就返回原来的类型