首页 > 建站教程 > JS、jQ、TS >  TypeScript的类型定义正文

TypeScript的类型定义

原始类型

文本

const value1 = ref<string>('我是文本')

数值

const value2 = ref<number>(100)

布尔

const value3 = ref<boolean>(false)

数组类型

两种写法:Array<string>和string[](推荐写法)

const value4 = ref<Array<string>>(['213', 'aaa']) 

const value5 = ref<string[]>(['aaa', '123','bbb']) 

元组类型

[]用来约束数组的个数和指定索引对应的类型

const position = ref<[number, number]>([39.2031, 23.2302])

联合类型

|表示由两个或多个其他类型组成的类型,也可以是其中的任意一种类型

const value6 = ref<(string | number | boolean)[]>(['aaa', 111, 'bbb', true])

type类型别名

type关键字可以为任意类型起别名

type commonType = (string | number | boolean)[]

const value7 = ref<commonType>(['aaa', 111, 'bbb', true])

函数类型

指定函数参数和返回值的类型

1. 单独指定参数、返回值的类型

// 普通函数

function add(str: string, num: number): string {

  return str + num

}

// 箭头函数

const add = (str: string, num: number): string => {

  return str + num

}

2. 同时指定参数、返回值的类型(仅适用于箭头函数),相当于在方法名和参数之间通过类似于箭头函数的写法为函数指定类型

const add: (str: string, num: number) => string = (str, num) => {

  return str + num

}

void类型

void 代表函数没有返回值

const sing= (str: string): void => {}


对象类型

直接使用{}描述对象结构,属性之间使用;(分号)分隔

const state = reactive<{ name: string; age: number; method(str: string): void }>({

  name: '张三',

  age: 18,

  method(str) {}

})

可选参数/属性

?代表可传或不传的参数/属性

// 可选参数

const add = (num1: number, num2?: number): void => { }

add(100)

// 可选属性

type commonType = {

    name: string

    age?: number

}

const val: commonType = {

    name: 'coco'

}

interface接口

interface关键字定义接口:指定一个可被多次使用的对象类型

interface commonInterface {

  name: string

  age?: number

}

const state = reactive<commonInterface>({ name: '张三' })

extends继承

extends关键字可继承接口的属性和方法

// 公共属性和方法

interface animal {

  name: string

  age: number

  say(str: string): void

}

// 特殊属性和方法

interface dog extends animal {

  leg: number

  jump(): void

}

const habaDog = reactive<dog>({

  name: '哈巴狗',

  age: 3,

  leg: 4,

  say(str) {},

  jump() {}

})

interface和type区别

相同:

1. 都可以描述属性和方法

interface Animal {

    name: string

    say(): void

}

type Car = {

    name: string

    run(): void

}

2. 都可以为对象指定类型

let obj1: Animal = { name: 'coco', say() { } }

let obj2: Car = { name: 'cici', run() { } }


3. 都可以扩展

    interface 使用 extends 实现

interface Animal {

    name: string

    say(): void

}

interface People extends Animal {

    age: number

}

let obj1: People = { name: 'coco', age: 4, say() { } }

    type 使用 & 实现

type Car = {

    name: string

    run(): void

}

type Benz = Car & {

    wheel: number

}

let obj2: Benz = { name: 'cici', wheel: 4, run() { } }

不同:

interface 接口可以合并,type不能

interface Animal {

    name: string

}

interface Animal {

    age: number

}

let obj: Animal = { name: "coco", age: 18 }

type 可以为任意类型指定别名,联合类型、元组等,interface 不能

type anyType1 = string | number | boolean

type anyType2 = [string | number | boolean]

字面量类型

字面量类型:某个特定的字符串、数值等作为类型使用

const changeDirection = (direction: 'Up' | 'Down' | 'Left' | 'Right') => {}

const changeStatus = (status: true | false) => {}

changeDirection('Up')

changeStatus(false)

枚举类型

枚举类型:表示一组明确的可选值,类似于字面量类型+联合类型的组合

enum关键字定义一组命名常量,首字母大写,逗号分隔,成员初始值默认为从0开始递增的数值

enum Direction {

  Up = 'UP',

  Down = 'DOWN',

  Left = 'LEFT',

  Right = 'RIGHT'

}

const changeDirection = (direction: Direction) => {

  console.log(direction)

}

changeDirection(Direction.Left)

typeof

typeof用来获取数据的类型,只能查询变量或者属性的类型

let arr = [1, 'aaa', 4]

let obj = {

  name: 'coco',

  age: 18

}

const value1 = ref<typeof arr>([100, 'bbb', 'aaa'])

const value2 = ref<typeof obj.name>('Tom')

class类

class的基本使用

    声明成员变量

    构造函数:成员初始化 ,通过this访问实例成员

    实例方法

class Animal {

  name: string

  age: number

  constructor(name: string, age: number) {

    this.name = name

    this.age = age

  }

  run(): void {}

}

const animal: Animal = new Animal('神秘物种', 100)

class继承(extends)

    通过extends关键字继承类的属性和方法

    通过super关键字调用父类的属性和方法

class Dog extends Animal {

  leg: number

  constructor(name: string, age: number, leg: number) {

    super(name, age)

    this.leg = leg

  }

  jump(): void {}

}

const habaDog: Dog = new Dog('哈巴狗', 3, 4)

class实现(implements)

    implements关键字实现接口的属性和方法

interface Singer {

  name: string

  sing(): void

}

class Cat implements Singer {

  name: string = 'Tom'

  sing() {

    console.log('say Hi')

  }

}

class可见性修饰符

public

public关键字是默认可见性,可直接省略,表示公有的,公有属性和方法可以被任何地方访问

// 父类Animal公有属性name、公有方法say()

class Animal {

    public name: string

    constructor(name: string) {

        this.name = name

    }

    public say(str): void {

        console.log(str)

    }

}

const animal: Animal = new Animal('神秘物种')

console.log(animal.name)  // 神秘物种

console.log(animal.say('我会说话'))  // 我会说话

// 子类Dog 可以访问父类公有属性和方法

class Dog extends Animal {}

const dog: Dog = new Dog('哈巴狗')

console.log(dog.name)  // 哈巴狗

console.log(dog.say('我会汪汪汪'))  // 我会汪汪汪

protect

protect关键字表示受保护的,子类的方法内部可以通过this来访问父类的受保护的成员变量,实例对象不可访问

// 父类Animal受保护的属性name、受保护的方法say()

class Animal {

  protected name: string

  constructor(name: string) {

    this.name = name

  }

  protected say(str: string): void {

    console.log(str)

  }

}

class Dog extends Animal {

  // this关键字获取父类受保护的属性和方法

  bark(): void {

    console.log(this.name)

    this.say('汪汪汪')

  }

}

const dog: Dog = new Dog('哈巴狗')

// dog实例对象无法访问父类受保护的属性和方法

console.log(dog.bark())  

private

private关键字表示私有的,仅在当前类中可见,其实例对象和子类都不能访问

class Animal {

  private name: string

  constructor(name: string) {

    this.name = name

  }

  private say(str: string): void {

    console.log(str)

  }

}

const animal: Animal = new Animal('神秘物种')

console.log(animal.name)  // 报错,实例对象不可访问private属性

console.log(animal.say)  // 报错,实例对象不可访问private方法

readonly只读修饰符

readonly关键字修饰的属性是只读的,不可用来修饰方法,被赋值的属性值不能被修改

class Animal {

  readonly name: string

  constructor(name: string) {

    this.name = name

  }

}

interface Direction {

  readonly Up: string

}

const haba = reactive<{readonly direction:string}>({

  direction: 'Up'

})

类型兼容性

类兼容

    只会比较实例成员,属性多的可以赋值给属性少

class Animal {

    public name!: string

}

class Cat {

    public name!: string

    public age!: string

}

let cat: Animal = new Cat()

console.log(cat)

    不会比较类的静态成员和构造函数

class Animal {

    public name!: string

    constructor(name: string) { }

}

class Cat {

    public name!: string

    public static age: number

    constructor(name: string) { }

}

let cat: Cat = new Cat('coco')

let animal: Animal = new Animal('coco')

cat = animal

animal = cat

    类的受保护属性和私有属性会影响兼容

        受保护属性:

class Animal {

    protected name!: string

}

class Cat {

    protected name!: string

}

let cat: Cat = new Cat()

let animal: Animal = new Animal()

animal = cat  // 报错

cat = animal  // 报错

        编译代码截图:

typescript

    私有属性:

class Animal {

    private name!: string

}

class Cat {

    private name!: string

}

let cat: Cat = new Cat()

let animal: Animal = new Animal()

animal = cat  // 报错

cat = animal  // 报错

    编译代码截图:

typescript

接口兼容

    属性多的可以赋值给属性少的

interface Animal {

    name: string

    age: number

}

interface Dog {

    name: string

    age: number

    leg: number

}

let animal: Animal = { name: 'coco', age: 3 }

let dog: Dog = { name: 'coco', age: 3, leg: 4 }

animal = dog

    interface 和 class 可以相互兼容

interface Animal {

    name: string

    age: number

}

class Dog {

    name!: string

    age!: number

    leg!: number

}

let animal: Animal = new Dog()

console.log(animal)

    interface 和 type 可以相互兼容

type Animal = {

    name: string

}

interface Car {

    name: string

}

let value1: Animal = { name: 'coco' }

let value2: Car = { name: 'cici' }

value1 = value2

value2 = value1

函数兼容

    参数个数:参数少的可以赋值给参数多的,也可以将联合类型的赋值给具体类型

let f1 = (x: number) => { }

let f2 = (x: number, y: number) => { }

let f3 = (x: number | string) => { }

f2 = f1

f1 = f3

    参数类型:相同位置的参数类型要相同

let f1 = (x: number) => { }

let f2 = (x: number) => { }

f2 = f1

f1 = f2

    返回值类型:返回值类型要相同,也可以将具体类型的赋值给联合类型

let f1 = (): number => 123

let f2 = (): number => 456

let f3 = (): (number | string) => 'hello'

f1 = f2

f2 = f1

f3 = f1

    函数重载:方法名相同,参数不同

function f1(x: number, y: number): number

function f1(x: string, y: string): string

function f1(x, y) {

    return x + y

}

f1(100, 200)

f1('aaa', 'bbb')

    函数重载:重载多的的可以赋值给重载少的

function f1(x: number, y: number): number

function f1(x: string, y: string): string

function f1(x, y) {

    return x + y

}

function f2(x: number, y: number): number

function f2(x, y) {

    return x - y

}

let fn = f2

fn = f1

交叉类型

&关键字:类似于接口继承,用来组合多个类型为一个类型(常用于对象)

interface Teacher { name: string }

interface Class { no: string }

type Course = Teacher & Class

let obj: Course = {

    name: 'Tom',

    no: '301'

}

交叉类型与接口继承的区别

相同: 都可以实现对象类型的组合

不同:

    交叉类型(&):同名属性,类型不同时会合并类型

    接口继承(extends):同名属性,类型不同时会冲突

类型断言和类型保护

使用联合类型的变量时,通过 类型断言 或者 类型保护的方式,能够确切告诉编译器它是哪一种具体类型

类型断言

    类型断言类似于类型转换,可以将一种类型强制转换成另外一种类型

<>

let value: any = "hello"

let len = (<string>value).length

console.log(len)

as

as 关键字断言变量的类型

let getValue = (): (string | number) => {

    let value = Math.random()

    return (value >= 0.5) ? 'hello' : 10.11

}

let value = getValue()

console.log(value)

if ((value as string).length) {

    console.log((value as string).length)

} else {

    console.log((value as number).toFixed())

}

类型保护

typeof

    typeof 关键字用来说明变量的数据类型,返回值是一个字符串,只能使用 === 或 !== ,只能保护 string | number | boolean | bigint | symbol | undefined | function 类型

    is 关键字一般用于函数返回值类型中,判断参数是否属于某一类型,返回值是布尔值

const getValue = (value: string | number): void => {

    if (typeof value === 'string') {

        console.log(value.length)

    } else {

        console.log(value.toFixed())

    }

}

getValue('hello')

getValue(100.11)

instanceof

    instanceof 关键字用于判断一个变量是否属于某个对象的实例,返回值是布尔值

class Animal {

    name!: string

    constructor(name: string) {

        this.name = name

    }

}

class Cat {

    age!: number

    constructor(age: number) {

        this.age = age

    }

}

const getObject = (obj: Animal | Cat): void => {

    if (obj instanceof Cat) {

        console.log(obj.age)

    } else {

        console.log(obj.name)

    }

}

getObject(new Animal('coco'))

getObject(new Cat(4))

in

    in 关键字检查对象是否存在一个特定的属性,使用该属性来区分不同的类型,通常返回值为布尔值

interface Animal {

    name: string

    leg: number

}

interface Car {

    name: string

    wheel: number

}

const getObject = (obj: Animal | Car): void => {

    if ('leg' in obj) {

        console.log(obj.leg)

    } else {

        console.log(obj.wheel)

    }

}

getObject({ name: 'coco', leg: 4 })


索引签名

数字索引签名

    通过定义接口用来约束数组

interface Animal {

    [index: number]: string

}

let arr: Animal = ['cat', 'dog']

console.log(arr)

字符串索引签名

    通过定义接口用来约束对象

interface Animal {

    [key: string]: string | number

}

let obj: Animal = {

    name: 'coco',

    age: 18,

}

console.log(obj)

never类型

never 类型表示那些永不存在的值的类型,一般用于抛出异常或不可能有返回值的函数

function error(msg: string): never {

    throw new Error(msg)

}

error('异常错误')

unknown类型

unknown 类型代表任何类型,被称作安全的 any

    任何类型都可以赋值给 unknown 类型

let val: unknown

val = 100

val = 'hello'

val = [100, 'hello', false]

val = {

    name: 'coco',

    age: 18

}

    不能将unknown类型赋值给其他类型,除非通过类型断言

let val: unknown = 18

let num: number

num = val  // 报错

num = <number>val

num = val as number

typescript

    只能对 unknown 类型进行 === 或 !== 操作, 不能进行其它操作,除非通过类型断言

let val: unknown = 100

type TestType1 = unknown & number

type TestType2 = unknown & string

let num: TestType1 = 123

let str: TestType2 = 'hello'

    unknown除了与any以外,与其他任何类型组成的联合类型最后都是unknown类型

let val: unknown = 100

type TestType1 = unknown | number | string | boolean

let obj: TestType1 = {

    name: 'coco'

}

    never 类型是 unknown 类型的子类型

type TestType = never extends unknown ? true : false

keyof unknown 等于 never

type TestType = keyof unknown

let val:TestType

typescript

    unknown 类型的值不能访问实例对象的属性和方法

class Animal {

    name!: string

    say(): void { console.log('hello') }

}

let a: unknown = new Animal()

a.name

a.say()

typescript