TypeScript学习(十)——缩小类型限制范围

typeof缩小类型限制范围

typeof的作用

function padLeft(padding: number | string, input: string) {
  // 因为repeat重复字符串api接收一个number类型的参数所以需要加typeof限制它的类型只能是number
  if (typeof padding === "number") {
    return " ".repeat(padding) + input;
  }
  return padding + input
}
console.log(padLeft(5,"你好"));
console.log(padLeft("     ","你好"));

在这里插入图片描述在这里插入图片描述

typeof返回的值

在这里插入图片描述

typeof能帮我们检测js疑难杂症之typeof null === ‘object’

function test(msg:object | string | null){
  /* js的typeof判断null时,返回的值也为‘object’,因此下面的判断依然会有可能导致程序报错
  而ts则可以在程序编译时帮我们检测出来 */
  if(typeof msg === 'object'){
    Object.keys(msg)
  }
}

在这里插入图片描述

条件判断 / && / || / ! 来缩小类型限制范围

解决上面的报错

function test(msg:object | string | null){
  /* js的typeof判断null时,返回的值也为‘object’,因此下面的判断依然会有可能导致程序报错
  而ts则可以在程序编译时帮我们检测出来 */
  if(typeof msg === 'object' && msg !== null){
    Object.keys(msg)
  }
}

在这里插入图片描述

js的判断不只是判断布尔值

js判断时,走否逻辑时的值不一定为布尔值false,以下值也可以是false
在这里插入图片描述

ts的检测是沿着作用域的开展的

function printAll(strs: string | string[] | null) {
  // 传入一个“”空字符串,ts判断为false不会走if里面的逻辑,从而会跳过下级作用域的检测
  if (strs) {
    if (typeof strs === "object") {
      for (const s of strs) {
        console.log(s);
      }
    } else if (typeof strs === "string") {
      console.log(strs);
    }
  }else {
    console.log('else');
  }
}
printAll("");

在这里插入图片描述

相等判断来缩小类型限制范围

=== / !== 严格相等性判断

ts校验在发现他们两个值相等时,会将他们的类型置为相同,当他们不同时,且至少有一个类型相同,那么他们的类型限制都会变成他们的之前类型限制的并集

function example(x: string | number, y: string | boolean) {
  if (x === y) {
    // 如果他们两个相等,取他们类型的交集
    x.toUpperCase(); 
    y.toLowerCase();
  } else {
    // 如果他们两个不想等,取他们类型的并集,且他们至少有一个类型相同
    console.log(x);
    console.log(y);
  }
}
example(1,"1");
function example(x: string | number, y: symbol | boolean) {
  // 如果他们类型没有相等的部分,那么他们必是不相等的,那么判断就会变得没有意义
  if (x === y) {
  } else {
  }
}
example(1,false);

在这里插入图片描述

== / != 宽松相等性判断

interface Container {
  value: number | null | undefined;
}
 
function multiplyValue(container: Container, factor: number) {
  // 宽松型的不等判断时,会将null和undefined作为同等情况
  if (container.value != null) {
    console.log(container.value);                 
    container.value *= factor;
  }
}

在这里插入图片描述

in判断来缩小类型限制范围

in只是在编译时判断是否可能是某类型,而不会认为这个属性一定会存在

type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };
 
function move(animal: Fish | Bird | Human) {
  if ("swim" in animal) {
    // in 判断符会去类型中找符合情况的Fish和Human类型作为这个if作用域中animal的类型。
    if(animal.swim){
      // 但是只是判断这个属性有没有可能会出现在这个类型中,而不会认为一定会存在这个属性。
      animal.swim();
    }
    } else {
  }
}
move({swim:function(){console.log("Hello World")}})

instanceof来缩小类型限制范围

instanceof的作用

x instanceof Foo检查x的原型链是否包含Foo.prototype。

function logValue(x: Date | string) {
  if (x instanceof Date) {
    // x.__proto__ === Date.prototype
    // 那么此时在这个if中的x的类型限制则为Date
    console.log(x.toUTCString());
  } else {
    // 反之x的类型为string
    console.log(x.toUpperCase());           
  }
}
logValue(new Date());
logValue("hello world");

在这里插入图片描述

=赋值来缩小ts的限制范围

ts在赋值的时候,会去看赋值的右边的值是什么类型从而将值的类型作为右边变量的类型限制(多个值即为联合类型)

/* 在let const var 等申明符声明变量赋值时,ts会去查看赋值右边的值
为什么类型,从而将这个类型赋值给右边的变量在此时为number | string */
let x = Math.random() < 0.5 ? 10 : "hello world!";
// 那么将number类型重新赋值给x不会报错
x = 1;
// 同理赋值string类型也不会报错
x = "Hello World";
console.log(x);
// 但是将number | string 的其它类型如boolean赋值给x则会抛出提示         
x = true;
console.log(x);

在这里插入图片描述

程序控制流缩小限制范围

一个变量的类型在程序运行的过程中,后根据程序运行流在类型的子集中根据使用情况不断变换类型限制

function example() {
  let x: string | number | boolean;
  x = Math.random() < 0.5;
  console.log(x); // boolean
  if (Math.random() < 0.5) {
    x = "hello";
    console.log(x);// string
  } else {
    x = 100;
    console.log(x);// number
  }
  return x;
}

约束唯一缩小限制范围

合并书写

interface Shape {
  kind: "circle" | "square";
  radius?: number;
  sideLength?: number;
}

function getArea(shape: Shape) {
  if (shape.kind === "circle") {
  // 判断是什么类型限制(只能是circle/square),radius不能为空
    return Math.PI * shape.radius! ** 2;
  }else {
    return shape.sideLength! ** 2
  }
}

拆分成多个类型减少判断

interface Circle {
  kind: "circle";
  radius: number;
}
 
interface Square {
  kind: "square";
  sideLength: number;
}
 
type Shape = Circle | Square;

function getArea(shape: Shape) {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.sideLength ** 2;
  }
}

never

缩小到没有类型限制

type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
  if ("swim" in animal) {
    if(animal.swim){
      animal.swim();
    }
  }else if("fly" in animal){
    if(animal.fly){
      animal.fly();
    } 
  }else {
    console.log(animal)
  }
}

在这里插入图片描述

never传递类型

never 类型可分配给每种类型。但是,没有任何类型可以分配给 never(除了 never 本身)。

type Shape = Circle | Square;
 
function getArea(shape: Shape) {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.sideLength ** 2;
    default:
    	// 如果前面两种情况都不满足,此时的shape类型为never,可以将never分配给never类型限制的变量
      const _exhaustiveCheck: never = shape;
      return _exhaustiveCheck;
  }
}

but

interface Circle {
  kind: "circle";
  radius: number;
}
 
interface Square {
  kind: "square";
  sideLength: number;
}

interface Triangle {
  kind: "triangle";
  sideLength: number;
}
 
type Shape = Circle | Square | Triangle;
 
function getArea(shape: Shape) {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.sideLength ** 2;
    default:
    	// 走完前面两个判断此时的shape类型限制为Triangle,除了never能分配给never之外,其它了类型不能分配给never
      const _exhaustiveCheck: never = shape;
      return _exhaustiveCheck;
  }
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LiuJie_Boom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值