二、TypeScript学习

对象类型

这里所说的对象类型,就是我们常说的函数、{}、数组、类

object, Object 和 {} 类型

  • object object 类型用于表示所有的非原始类型,即我们不能把 number、string、boolean、symbol等 原始类型赋值给 object。在严格模式下,null 和 undefined 类型也不能赋给 object。
let object: object;
object = 1; // 报错
object = "a"; // 报错
object = true; // 报错
object = null; // 报错
object = undefined; // 报错
object = {}; // 编译正确
  • Object

大 Object 代表所有拥有 toString、hasOwnProperty 方法的类型 所以所有原始类型、非原始类型都可以赋给 Object(严格模式下 null 和 undefined 不可以)

let bigObject: Object;
object = 1; // 编译正确
object = "a"; // 编译正确
object = true; // 编译正确
object = null; // 报错
ObjectCase = undefined; // 报错
ObjectCase = {}; // ok
  • {}

{} 空对象类型和大 Object 一样 也是表示原始类型和非原始类型的集合

在 TypeScript 中,我们通过 Class 关键字来定义一个类

class Person {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  sayHi(): void {
    console.log(`Hi, ${this.name}`);
  }
}

数组

const flag1: number[] = [1, 2, 3];
const flag2: Array<number> = [1, 2, 3];

函数

函数声明

function add(x: number, y: number): number {
  return x + y;
}

函数表达式

const add = function(x: number, y: number): number {
  return x + y;
}

接口定义函数

interface Add {
  (x: number, y: number): number;
}

可选参数

function add(x: number, y?: number): number {
  return y ? x + y : x;
}

默认参数

function add(x: number, y: number = 0): number {
  return x + y;
}

剩余参数

function add(...numbers: number[]): number {
  let sum = 0;
  for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
  }
  return sum;
}

函数重载

函数重载或方法重载是使用相同名称和不同参数数量或类型创建多个方法的一种能力。

function add(x: number, y: number): number;
function add(x: string, y: string): string;
function add(x: any, y: any): any {
  return x + y;
}

上面示例中,我们给同一个函数提供多个函数类型定义,从而实现函数的重载

需要注意的是:

[!note|style:flat] 函数重载真正执行的是同名函数最后定义的函数体 在最后一个函数体定义之前全都属于函数类型定义 不能写具体的函数实现方法 只能定义类型

具体示例原理可参考

类型推论

如果没有明确的指定类型,那么 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 类型

[!note|style:flat] 注意:交叉类型取的多个类型的并集,但是如果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'.

类型守卫

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

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

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

  • 1、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'});
  • 2、typeof 关键字
function isTypeof( val: string | number) {
  if (typeof val === "number") return 'number'
  if (typeof val === "string") return 'string'
  return '啥也不是'
}

[!note|style:flat] typeof 只支持:typeof 'x' === 'typeName' 和 typeof 'x' !== 'typeName',x 必须是 'number', 'string', 'boolean', 'symbol'。

  • 3、instanceof
function creatDate(date: Date | string){
    console.log(date)
    if(date instanceof Date){
        date.getDate()
    }else {
        return new Date(date)
    }
}
  • 4、自定义类型保护的类型谓词
function isNumber(num: any): num is number {
    return typeof num === 'number';
}
function isString(str: any): str is string{
    return typeof str=== 'string';
}

results matching ""

    No results matching ""