TypeScript学习笔记之四

270 阅读3分钟

联合类型和交叉类型

联合类型

联合类型通常出现在参数要多种类型的时候,代码如下:

function person(name: string | undefined) {
  if (typeof name === 'string') {
    console.log('我的名字是' + name);
  } else {
    console.log('参数的值是undefined');
  }
}
person('jack');
person(undefined);

联合类型描述的值可以是几种类型之一,我们通常使用"|"来分割每种类型,代码如下:

function person(age: string | number |undefined) {
  if (typeof age === 'string') {
    console.log(`我的年龄是${age}岁`);
  } else if(typeof age === 'number') {
    console.log('我的年龄是数字' + age);
  }else{
    console.log('参数值是undefined');
  }
}
person('18');
person(18);
person(undefined);

值得注意的是联合类型只能访问通用的成员,代码如下:

interface Bird {
  fly(): void;
  layEggs(): void;
}

interface Fish {
  swim(): void;
  layEggs(): void;
}

declare function getSmallPet(): Fish | Bird;

let pet = getSmallPet();
pet.layEggs();
pet.swim();//属性“swim”在类型“Bird | Fish”上不存在。类型“Bird”上不存在属性“swim”

从上面的代码我们可以得知,如果该值具有类型A | B,该值只能具有A B都具有的成员。

可辨识的联合

使用可辨识的联合是使用联合的一种常见的技术,该联合主要是具有单个共享字段的联合,代码如下:

type NetworkLoadingState = {
  state: "loading";
};

type NetworkFailedState = {
  state: "failed";
  code: number;
};

type NetworkSuccessState = {
  state: "success";
  response: {
    title: string;
    duration: number;
    summary: string;
  };
};
type NetworkState =
  | NetworkLoadingState
  | NetworkFailedState
  | NetworkSuccessState;

function logger(state: NetworkState): string {
  switch (state.state) {
    case "loading":
      return "Downloading...";
    case "failed":
      return `Error ${state.code} downloading`;
    case "success":
      return `${state.response.title} load ${state.response.summary},lasted ${state.response.duration}s`;
  }
}
let loadingState:NetworkState = {
  state:"loading"
};
let failedState:NetworkState = {
  state:"failed",
  code:404
};
let successState:NetworkState = {
  state:"success",
  response:{
    title:'NetWork',
    duration:0.2,
    summary:"successful"
  }
};
console.log(logger(loadingState));
console.log(logger(failedState));
console.log(logger(successState));

交叉类型

交叉类型和联合类型紧密相关,两者的使用方式却不太相同,交叉类型是把多种类型组合成为一种类型,交叉类型通过运算符"&"将现有类型加在一起,以获得具有所需功能的单个类型,代码如下:

interface NetworkLoadingState {
  state: string;
};

interface NetworkFailedState {
  failed: boolean;
};

interface NetworkSuccessState {
  success: boolean;
};
type NetworkState = NetworkLoadingState & NetworkFailedState & NetworkSuccessState

const logger = (response: NetworkState) => {
  if (response.state) {
    console.log(response.state);
  }else if(response.failed){
    console.log(`failed`)
  }else if(response.success){
    console.log(`success`)
  }
};
let loadingState:NetworkState={
  state:"loading",
  failed:false,
  success:false
};
let failedState:NetworkState={
  state:"",
  failed:true,
  success:false
};
let successState:NetworkState={
  state:"",
  failed:false,
  success:true
};
logger(loadingState);
logger(failedState);
logger(successState);

上面代码主要是基础类型属性的合并,那么非基础类型属性能不能被合并呢,代码如下:

interface num {
  code: number
};
interface str {
  title: string
};
interface obj {
  data: any
}

interface NetworkLoadingState {
  state: string;
  all:num
};

interface NetworkFailedState {
  failed: boolean;
  all:str
};

interface NetworkSuccessState {
  success: boolean,
  all:obj
};
type NetworkState = NetworkLoadingState & NetworkFailedState & NetworkSuccessState

const logger = (response: NetworkState) => {
  if (response.state) {
    console.log(response.all.data.msg);
  } else if (response.failed) {
    console.log(response.all.data.msg);
  } else if (response.success) {
    console.log(response.all.data.msg);
  }
};
let loadingState:NetworkState={
  state:"loading",
  failed:false,
  success:false,
  all:{
    code:0,
    title:'加载中',
    data:{
      msg:"数据加载中"
    }
  }
};
let failedState: NetworkState = {
  state: "",
  failed: true,
  success: false,
  all:{
    code:404,
    title:'加载失败',
    data:{
      msg:"数据加载失败"
    }
  }
};
let successState: NetworkState = {
  state: "",
  failed: false,
  success: true,
  all:{
    code:200,
    title:'加载成功',
    data:{
      msg:"数据加载成功"
    }
  }
};
logger(loadingState);
logger(failedState);
logger(successState);

如代码所示,我们可以成功合并存在相同的成员的接口,且该成员类型是一个非基础数据类型。

类型别名

所谓的类型别名就是用一个新的名字代替老的一个类型,代码如下

type msg = string | number;

let greet = (message: msg) => {
  console.log(message);
};
greet('message');
greet(11);

文字类型

字符串文字类型

在实际情况中,字符串文字类型和联合类型,类型守卫和类型别名很好的结合在一起,代码如下:

type State = "loading" | "false" | "success";
class NetWorkState{
  NetWorkFun(code: number,state: State) {
    if (state === "loading") {
      console.log('DownLoading');
    } else if (state === "false") {
      console.log(code);
    } else if (state === "success") {
      console.log(code);
    } else {
      console.log('Error')
    }
  }
}

let button = new NetWorkState();
button.NetWorkFun(0, "loading");
button.NetWorkFun(404, "false");
button.NetWorkFun(200, "success");
button.NetWorkFun(200, "noState");//“noState”类型的参数不能赋值给“State”类型的参数。

数值文字类型

数值文字类型的作用与字符串文字类型的作用相同,代码如下:

type Code = 0 | 404 | 200;
class NetWorkState{
  NetWorkFun(code: Code,state: string) {
    if (code === 0) {
      console.log(state);
    } else if (code === 404) {
      console.log(state);
    } else if (code === 200) {
      console.log(state);
    } else {
      console.log('Error')
    }
  }
}

let button = new NetWorkState();
button.NetWorkFun(0, "loading");
button.NetWorkFun(404, "false");
button.NetWorkFun(200, "success");
button.NetWorkFun(500, "noState");//类型'500'的参数不能赋值给类型'Code'的参数。

布尔值文字类型

在写代码的过程中我们可以使用布尔值文字类型来约束相互关联的对象值,代码如下:

interface NetWorkSuccess {
  isValid: true;
  reason: null;
}

interface NetWorkFailure {
  isValid: false;
  reason: string;
}

type NetWorkResult = NetWorkSuccess | NetWorkFailure;
function NetWork(result: NetWorkResult) {
  if(result.isValid){
    console.log(result.reason);
  }else if(!result.isValid){
    console.log(result.reason);
  }
}
let ResFailure: NetWorkResult = {
  isValid: false,
  reason: "网络连接失败"
}
let ResSuccess:NetWorkResult = {
  isValid: true,
  reason: null,
}
NetWork(ResFailure);
NetWork(ResSuccess);