美文网首页js css html
TS中type和interface类型守卫

TS中type和interface类型守卫

作者: wyc0859 | 来源:发表于2022-03-14 10:05 被阅读0次

接口

interface Product {
  id?: number; //可选参数
  name: string;
  price: number;
  count: number;
  rate: () => void; //函数
  [key: string]: any; //扩展参数
}

function calToal(product: Product) {
  console.log("product总价:", product.price * product.count);
  product.rate();
}

calToal({
  name: "手机",
  price: 3800,
  count: 2,
  rate: () => {
    console.log("评价一下");
  },
  msg: "string",
}); //函数接收参数定义的是Product接口,所以必须对应,少个必须参数都不行

通用函数类型

type commonFunc = (...args: any) => any 
interface commonFuncInter {
  eat: (...args: any) => any
}
//上面使用是 commonFuncInte[eat]

//下面使用是 commonFuncInter
interface commonFuncInter {
  (...args: any): any
}

联合类型

interface Goods {
  name: string;
  price: number;
  height: number;
  weight: number;
}
function phone(param: Product | Goods) {
  console.log("phone:", param, param.name); 
//只能点出2个接口共有的属性,如count或weight都会报错
  console.log("函数中类型:", typeof param);
  //无论是type或interface都一样,这里是object。就算在外面打印都是object
}
const xiaomi: Goods = {
  name: "mi",
  price: 2988,
  height: 1.2,
  weight: 2,
};
console.log("定义对象时的类型:", typeof xiaomi); //object
phone(xiaomi);

联合类型技巧性使用场景

type isTrue = Boolean | 1 | 0;
function mounted(state: isTrue) {
  if (state) {
    console.log("yes");
  } else {
    console.log("no");
  }
}
mounted(1);

type 和 interface 区别

区别1: 定义类型范围不同
interface 只能定义对象类型或接口当名字的函数类型
type 可以定义任何类型,包括基础类型、联合类型、交叉类型、元组

type num = number;
type baseType = string | number | symbol; // 定义联合类型1

// 定义联合类型2
interface Category {
  name: string;
}
interface Pros {
  pname: string;
  price: number;
}
type CatePro = Category | Pros;
const product: CatePro = { name: "手机类" };

// 定义元组类型
type TypCatePro = [Category, Pros];
const proTwo: TypCatePro = [{ name: "手机类" }, { pname: "华为", price: 4999 }];

区别2:type没有继承功能,接口可以继承(但应用场景很少见)
区别3:type的交叉类型(&),可让类型中的成员合并成一个新的type类型,但接口不能交叉合并

type Group = { groupName: string; memberNum: number };
type GroupInfoLog = { info: string; groupName: string };
type GroupMemeber = Group & GroupInfoLog; //type 交叉类型合并
let test: GroupMemeber = {
  groupName: "aa",
  memberNum: 168,
  info: "bb",
};
//交叉合并了,赋值时,参数少一个都不行

区别4:接口可以合并声明
定义两个相同名称的接口会合并声明,定义两个同名的type会出现编译错误

interface Error {
  name: string;
}
interface Error {
  message: string;
  stack?: string;
}
// 接口合并
let error: Error = {
  message: "空指针",
  name: "NullPointException",
};

接口和属性同名

interface typOther {
  typOther: (state: string, commit: any) => void;
}
let method: typOther = {
  typOther: (state: string, commit: any) => {},
};
method.typOther("abc", [1, 3, 5]);

//接口当名字用,不是简单的缩写,并且和上面不相同
interface typState {
  (state: string, commit: any): void;
}
let action: typState = (state: string, commit: any): void => {
  console.log("state:", state);
};
action("abc", [1, 3, 5]);

自定义类型守卫

定义:自定义守卫是通过 {形参 is 类型} 返回布尔值的赋予类型守卫的能力的条件表达式
is 类型是: 接口、类、基础类型数据(string,number,boolean,null,undefined,void,symbol)

class Parent {
  public xingshi!: string;
  constructor() {}
}
class Son extends Parent {
  public name!: string;
  public sex = "男";
  game() {
    console.log("喜欢游戏");
  }
}
class Daughter extends Parent {
  public name!: string;
  public sex = "女";
  picture() {
    console.log("喜欢图画");
  }
}
//自定义类型守卫
function isSon(str: any): str is Son {
  return str instanceof Son;
}
function isString(str: any): str is string {
  return typeof str === "string";
}

function funa(Lei: Parent) {
  if (isSon(Lei)) {
    Lei.game();
  } else if (isString(Lei)) {
    console.log("这是个字符串");
  } else {
    console.log("其他");
  }
}
funa(new Son()); //喜欢游戏
funa(new Daughter()); //其他
export {};

相关文章

网友评论

    本文标题:TS中type和interface类型守卫

    本文链接:https://www.haomeiwen.com/subject/imqrdrtx.html