TypeScript--类型问题汇总

学过js你认识的类型:booleannumberstringundefinednullsymbolobject

你可能不认识的类型:voidanyunknownnever

  • 类型声明是TS非常重要的一个特点,通过类型声明可以指定TS中变量(参数、形参)的类型。指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错
  • TS拥有自动的类型判断机制:当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型,所以如果你的变量的声明和赋值时同时进行的,可以省略掉类型声明
  • js中的函数是不考虑参数的类型个数的,而TS的函数参数不仅限制个数还限制类型。

我们先来看看,TypeScript给变量指定类型的语法(类型注解)是什么

对象

一般来说,我们对于对象的类型检查一般是检查对象中有哪些属性,属性是什么类型。

可以用{} 来指定对象中可以包含哪些属性 语法:{属性名: 属性类型, ...}

属性多了少了都不行

可选属性,在属性名后面加一个 ?

let obj: {name: string, age?: number}
obj = {name: 'yk', age: 18}
obj = {name: 'yk'}

如果后续属性不确定叫什么名字,也不确定是什么类型,那么可以这样写[propName: string]: unknown

// 定义对象结构
let obj: { name: string, [propName: string]: unknown }
obj = {name: 'yk', age: 18, gender: 'male'}

数组

比较常用的就是这种方式: 在元素类型后面接上 []:

let arr: number[] = [1, 2, 3]
let arr2: string[] = ['y', 'k']

还有一种是使用泛型(后面会说什么是泛型):

let list: Array<number> = [1, 2, 3]
let list2: Array<string> = ['y', 'k']
let list: Array<number | string> = [1, 2, 3, 'yk']

1. 回顾es6

类:定义了一切事物的抽象特点,面向对象的三大特点:封装、继承、多态。

三种变量: public、private(只能在当前类里面访问和使用)、protected(子类中可以访问和使用,外部不行)

类的静态属性可直接访问:static;只读属性 readonly

引用父类的属性和方法:super


class Animal = {
    constructor(name) {
        this.name = name
    }
   protected run() {
        return `${this.name} is running`
    }
}
const xiaobao = new Animal('xiaobao')
 class Cat extends Animal {
    static categories = ['mammal']
    constructor(name) {
        super(name)
        console.log(name)
    }
    run() {
        return 'Meow,' + super.run()//这里不会报错
    }
}
console.log(Cat.categories)
const maomao = new Cat('maomao')
console.log(maomao.run());//protected 这里会报错

2. class与接口搭配 ,加约束类型implements,实现继承

interface Radio {
    switchRadio(trigger: boolean):viod;
}
interface Battery {
    checkBatteryStatus():viod;
}
interface RadioWidthBattery extends Radio {
    checkBatteryStatus():viod;
}

//利用接口契约方式,Car上面必须要switchRadio有这个方法
class Car implements Radio {
    switchRadio(trigger: boolean);//删掉就会报错
}
//利用接口契约方式,Car上面必须要switchRadio有这个方法
class cellPhone implements RadioWidthBattery {
    switchRadio(trigger: boolean){

    }
    checkBatteryStatus(){

    };
}

泛型 generics

动机:看做是一个占位符,可以动态的传入确定的类型

1. 作用于:类型的传递。

function echo<T>(arg:T):T{
    return arg
}
const result = echo(true)
function swap<T, U>(tuple:[T, U]): [U, T] {
    return [tuple[1], tuple[0]]
}
const result2 = swap(['string', 123])
// const result2:[number,string] 注意返回的结果顺序哦
// 第一个可以使用number的方法
result2[0].toFixed()
            toString()
// 第二个可以使用string的方法
result2[1].chartCodeAt()
            concat()

2. 利用接口来约束泛型:传入的参数必须包含某个属性

interface IwithLength {
    length: number
}
function echoWithLength<T extends IwithLength>(arg: T):T {
    return arg
}
// 约束传入参数必须包含length 属性或者方法
const str = echoWithLength('str')
const str = echoWithLength({ length: 10,width: 10})
const str = echoWithLength([1,2,3])

 

类型断言

有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:

第一种

let someValue: unknown = "this is a string";
let strLength: number = (someValue as string).length;
function getLength(input: string | number): number {
    const str = input as string
    if (str.length) {
        return str.length
    } else {
        const number = input as number
        return number.toString().length
    }
}

// type guard
function getLength(input: string | number): number {
    if (typeof input === 'string') {
        return str.length
    } else {
        return number.toString().length
    }
}

第二种

let someValue: unknown = "this is a string";
let strLength: number = (<string>someValue).length;

 

特殊类型介绍

1. any

any 表示的是任意类型,一个变量设置类型为 any 后,相当于对该变量关闭了TS的类型检测。

隐式any:如果只声明变量不指定类型不给变量赋值,变量就是any类型的

当把any类型的变量可以赋值给其他类型的变量,不会报错,会把别的变量的类型改掉

any类型是多人协作项目的大忌,很可能把Typescript变成AnyScript,通常在不得已的情况下,不应该首先考虑使用此类型。

2. unknown

unknownany的区别就是,将unknown类型变量赋值给其他任意类型的变量时,会报错

3.viod

相信熟悉Java或者C的同学应该对void也不会陌生,当函数没有返回值的时候,定义函数的返回值类型就是void

其实我们知道,在JavaScript中,如果定义一个函数不写返回值,那么它默认是返回 undefined 的~

什么都不返回

function fn(): void {
}

只写一个return

function fn(): void {
  return 
}

返回一个undefined

function fn(): void {
  return undefined
}

我们返回一个null也是可以的

function fn(): void {
  return null
}

除了以上的几种情况,其他情况都是不行的

也就是说只有nullundefined可以赋给void

其实在JS中void是一种操作符,可以让任何表达式返回undefined

void 0 // undefined

为什么要这样呢,因为undefined在JS中不是一个保留字,可以通过声明变量来覆盖它

4.never

never 表示永远不会返回结果

  1. 报错
function error(): never{
    throw new Error('报错了!')
}
  1. 死循环
function endless(): never{
    while(true) {}
}

5.tuple

元组是TS新出的类型,表示固定长度的array;元组中包含的元素,必须与声明的类型一致,而且不能、不能,甚至顺序都不能不一样

6.enum

可以定义一个Gender枚举类

enum Gender {
  'male',
  'female'
}

怎么使用呢,就和使用对象中的属性一样Gender.male

let person = { name: 'yk', gender: Gender.male }

枚举类中,将这些属性都默认定义成了数字,默认是从0开始

我们看看这个枚举类转义成JS是什么 www.typescriptlang.org/play

"use strict";
var Gender;
(function (Gender) {
    Gender[Gender["male"] = 0] = "male";
    Gender[Gender["female"] = 1] = "female";
})(Gender || (Gender = {}));

通过看这个js代码,我们可以发现,这不是简单的赋值为0,而是套了一层,在JavaScript中,赋值运算符返回的值是被赋予的值。也就是说,这个枚举类是支持正反映射的,什么意思呢

不但可以通过Gender.male取到0还可以通过Gender[0]取到male

console.log(Gender.male) // 0
console.log(Gender['male']) // 0
console.log(Gender[0]) // male


版权声明:本文为qq_36711388原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。