Ts 类型收窄
关于类型收窄(Narrowing),市面上已经有很多文章去描述了,本博客在此来讨论各种类型收窄方法的应用场景。
背景
默认读者了解什么是ts,
默认读者了解类型系统
默认读者使用规范的ts风格编程
应用场景
类型收窄是将类型从不太精确的类型推导为更精确的类型的过程。
function fn (a: number | string | xxx){
// 根据传入参数不同类型,作相应操作
}
一 、 typeof 收窄
适用于:
string number bigint boolean symbol undefined object function
无法判断的类型:
null 数组对象 自定义类型对象 日期对象
原因:
以上无法判断类型的对象在typeof 均返回 ‘object’
二、 instanceof 收窄
适用于:
日期对象、数组对象、正则对象
无法判断:
简单数据类型:如:string number boolean等、ts自定义类型
原因:
instanceof 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。而以上简单数据类型在js中并不是一个对象。
三、使用 in 运算符进行收窄
适用于:
两个类型具有不用的属性。
type Circle = {
radius: number
}
type square= {
width: number
height: number
}
function A(shape: Circle | square) {
if ('radius' in shape) {
// do something about Circle
}
if ('width' in shape && 'height' in shape) {
// do something about square
}
不适用: 复杂对象 函数 如下
type A = {
name:string
}
type B = {
name:string
[k:string} : string
}
type A = ()=> void
type B = (xxx:number)=> string
// 注意 区分函数 建议如下写法
type A = {
(name:string):void
kand:'FnA'
}
四、 类型为此 is 做类型收窄
比较万能
type Rect = {
height: number
width: number
}
type Circle = {
center: [number, number]
radius: number
}
const F1 = (a: Rect | Circle)=>{
if(isRect(a){
// 如果不遵循如下 'x is Rect' 语法,则变量a 依旧无法识别为Rect,无法正常点出height
a.height = 1231231
}
}
function isRect(x:Rect | Circle): x is Rect {
retrun 'height' in x && 'width' in x
}
五 可辨别联合
interface Circle {
kind: "circle"; // 字符串字面量类型
radius: number;
}
interface Square {
kind: "square"; // 字符串字面量类型
sideLength: number;
}
type Shape = Circle | Square;
// 两个联合类型有用一个字段,此字段用来区分类型,名字可自定义
function f1(shape: Shape) {
if(a.kind === 'circle'){
// 可順利点出 a.radius
console.log(a.radius)
}
}
注意: 联合对象用于区分类型的字段不能是对象。
interface Circle {
kind: {name:'Circle'}
radius: number;
}
// 无法区分
此篇博客所有知识点来源于:
方应杭讲编程。