类型推论

如果没有明确的指定类型,那么 TypeScript 会依照类型推论的规则推断出一个类型。

let x = 1;
x = true; // 报错

上面的代码等价于

let x: number = 1;
x = true; // 报错

通过上述示例我们可以看出,我们没有给 x 指定明确类型的时候,typescript 会推断出 x 的类型是 number。

而如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查:

let x;
x = 1; // 编译正确
x = true; // 编译正确

类型断言

某些情况下,我们可能比typescript更加清楚的知道某个变量的类型,所以我们可能希望手动指定一个值的类型

类型断言有两种方式

尖括号写法

let str: any = "to be or not to be";
let strLength: number = (<string>str).length;

as 写法

let str: any = "to be or not to be";
let strLength: number = (str as string).length;

非空断言

在上下文中当类型检查器无法断定类型时,可以使用缀表达式操作符 ! 进行断言操作对象是非 null 和非 undefined 的类型,即x!的值不会为 null 或 undefined

let user: string | null | undefined;
  console.log(user!.toUpperCase()); // 编译正确
  console.log(user.toUpperCase()); // 错误

确定赋值断言

let value:number
console.log(value); // Variable 'value' is used before being assigned.

我们定义了变量, 没有赋值就使用,则会报错

通过 let x!: number; 确定赋值断言,TypeScript 编译器就会知道该属性会被明确地赋值。

let value!:number
console.log(value); // undefined 编译正确

联合类型

联合类型用|分隔,表示取值可以为多种类型中的一种

let status:string|number
status='to be or not to be'
status=1

类型别名

类型别名用来给一个类型起个新名字。它只是起了一个新名字,并没有创建新类型。类型别名常用于联合类型。

type count = number | number[];
function hello(value: count) {}

交叉类型

交叉类型就是跟联合类型相反,用&操作符表示,交叉类型就是两个类型必须存在

interface IpersonA{
  name: string,
  age: number
}
interface IpersonB {
  name: string,
  gender: string
}

let person: IpersonA & IpersonB = { 
    name: "师爷",
    age: 18,
    gender: "男"
};

person 即是 IpersonA 类型,又是 IpersonB 类型

注意:交叉类型取的多个类型的并集,但是如果key相同但是类型不同,则该key为never类型

interface IpersonA {
    name: string
}

interface IpersonB {
    name: number
}

function testAndFn(params: IpersonA & IpersonB) {
    console.log(params)
}

testAndFn({name: "黄老爷"}) // error TS2322: Type 'string' is not assignable to type 'never'.

类型守卫

类型保护是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内。换句话说,类型保护可以保证一个字符串是一个字符串,尽管它的值也可以是一个数值。类型保护与特性检测并不是完全不同,其主要思想是尝试检测属性、方法或原型,以确定如何处理值。

换句话说:类型守卫是运行时检查,确保一个值在所要类型的范围内

目前主要有四种的方式来实现类型保护:

in 关键字

interface InObj1 {
    a: number,
    x: string
}
interface InObj2 {
    a: number,
    y: string
}
function isIn(arg: InObj1 | InObj2) {
    // x 在 arg 打印 x
    if ('x' in arg) console.log('x')
    // y 在 arg 打印 y
    if ('y' in arg) console.log('y')
}
isIn({a:1, x:'xxx'});
isIn({a:1, y:'yyy'});

typeof 关键字

function isTypeof( val: string | number) {
  if (typeof val === "number") return 'number'
  if (typeof val === "string") return 'string'
  return '啥也不是'
}

typeof 只支持:typeof ‘x’ === ‘typeName’ 和 typeof ‘x’ !== ‘typeName’,x 必须是 ‘number’, ‘string’, ‘boolean’, ‘symbol’。

instanceof

function creatDate(date: Date | string){
    console.log(date)
    if(date instanceof Date){
        date.getDate()
    }else {
        return new Date(date)
    }
}

自定义类型保护的类型谓词

function isNumber(num: any): num is number {
    return typeof num === 'number';
}
function isString(str: any): str is string{
    return typeof str=== 'string';
}