希曼日记

TypeScript-基础知识

本页目录 7
  1. 泛型
  2. 类型
  3. 类型断言
  4. 别名
  5. 接口
  6. 其他

可选参数

?关键字来表示该参数可选

可选参数必须放在后面

const fn = (x: string, y?: string): string
{
  if (y) {
    return x + y
  }
  return x //8
}
const fn1 = fn('8')

剩余参数

...关键字定义一个剩余参数

剩余参数接收前面接受不完的参数(如果有)

const Fn1: (x: string, ...args: string[]) => string[] = function (x: string, ...args: string[]): string[] {
  console.log(x) // a
  args.unshift(x)
  console.table(...args) //['a', 'b', 'c', 'd', 'e']
  return args
}

const fn1 = Fn1('a', 'b', 'c', 'd', 'e')
console.log(fn1)

函数重载

重载的必要条件:

  1. 两个或以上重名函数,函数参数可能不相同(函数重载声明)

  2. 函数声明 缺点:函数重载声明过多 解决方案:使用泛型可重构的函数重载

//函数重载声明
function add (x: string, y: string): string
function add (x: number, y: number): number

``

//函数声明
function add (x: string | number, y: string | number): string | number {
  if (typeof x === 'string' || typeof y === 'string') return `${ x } - ${ y }`
  else return x + y
}

const add1 = add(10, 20) //30
const add2 = add(20, '20') //error
const add3 = add('str', 'ing') //string
const add4 = add('30', '40') //
使用泛型可实现少代码的函数重载
//重构以上代码

function add<T> (x: T, y: T): T {
  if (x<string> || y<string>) {
    return `${ x } - ${ y }`
  }
  else {
    return x + y
  }
}

const add1 = add<number>(10, 20) //30
const add2 = add<number | string>(20, '20') //error
const add3 = add<string>('str', 'ing') //string
const add4 = add<string>('30', '40')

class

//基类/超类
class Person {

}

//派生类(通过extends继承的类就称为派生类,被继承的类就叫基类/超类,之间的关系就叫父子类)
class DerivedClass extends Person {

}

const person = new Person()
const derivedClass: Person = new DerivedClass()

泛型

应用场景: 在初始化时不确定要传入的类型,只有在传入时才确定的类型使用

单个泛型参数

function add<T> (x: T, y: number): Array<T> {
  const arr = string[] = []
  for (let i = 0; i < y; i++) {
    arr.unshift(x)
  }
  return arr
}

const str = add('a', 'b', 'c')
interface IAni {
  cont: number
}

function <T> (x: <T extends IAni>): T {}

类型

type定义一个类型

//定义
type Name = string
type NameResolver = () => string
type NameOrResolver = Name | NameResolver

//使用
const name: Name = 'lisa'

//n的类型可能是字符串,或者是一个函数的返回值为字符串 返回类型:字符串
function getName (n: NameOrResolver): Name {
  //类型断言 <string> 断定此时的类型为string  
  if (n<string>) {
    //返回该字符串
    return n
  }
  //执行该函数
  else {
    return n()
  }
}

const str = getName('str')

类型断言

使用类型断言来给变量明确的类型

使用 <类型>断定此时为一个<>里的类型

<> 尖括号形式来表示类型断言

function (x: string | number): number | undefined {
  if (x <number>) {
    return x
  }
  else if (isNaN(x <string>)) {
    return Number(x)
  }
  else {
    return 'not a number'
  }
}

as 关键字表示类型断言

const arr = [1, 2, 3, 4]
arr.find(e => e > 2) //ts报错 此时ts提示arr的类型为number | undefined
const arr1 = arr as number //给arr添加类型断言 就不会报错
arr.find(e => e > 2) //3

别名

可以为interface接口,class类,function函数等起一个别名

type Name
:
string

function (n: Name) {
  return n
}

接口

定义一串来限制对象/函数/类的属性类型

//定义一个接口明确限制对象的属性类型
interface Person {
  id: number,
  name: string,
  age: number | string,
  gender: string,
  isShow?: boolean
}

//定义一个接口来限制函数的参数类型    
interface IFn {
  //调用签名
  (str1: string, str2?: string): string
}

const obj: Person = {
  id: 1,
  name: 'lisa',
  age: '20',
  gender: 'woman',
}

const fn: IFn = (str1: string, str2?: string): string => {
  if (str2) {
    return str1 + str2
  }
  return str1
}

[] 关键字给动态对象类型添加接口

[属性名称(任意)
:
属性类型
] :
类型

interface Person {
  [key: string]: string //限定属性类型为字符串 则对象的值必须也是字符串类型
}

const obj = {}
obj.name = 'lisa'
obj.age = 18 //报错 不是字符串

readonly 只读属性 限定接口类型的值不可修改,一旦赋值之后就不能修改

interface Type {
  readonly name: string
}

const obj: Type = {
  name: 'lisa'
}
obj.name = 'sum' // err 无法分配到 "name" ,因为它是只读属性

其他

声明文件

  • 自定义类型提示(Vanilla)
declare var xxx: (变量: 类型) => 返回类型

描述一类事物的抽象特征

类成员(属性)

语法

修饰符 成员名 = 值

写法

class 类名{
  public/private/proected name: type = value //不推荐
}

语法

public
/proected/
private
成员名 : 类型
constructor(成员名
:
类型
)
{
  this.成员名 = 成员名
}

写法

class ClassName {
  public name: type

  constructor (name: string) {
    this.name = name
  }
}

抽象类:

通过adstract关键字定义一个抽象类

  1. 抽象类不能实例化

  2. 抽象类的价值是被当作基类/超类来使用 主要给派生类定义类型和抽象的方法

  3. 抽象类可以具体描述

  4. 抽象类在抽象方法时不用{} 但需要空的返回值类型void

  5. 抽象类不建议/不经常使用抽象属性

abstrace

class Person {
  abstract name: string = 'name' //不推荐
  abstrace

  eat (): void //空的返回值
  abstract sayHi (): void { //可以具体书写方法
    console.log("hi")
  }
}

类定义

class Person {}

readonly 只读属性

class Person {
  //前缀修饰符
  readonly name: string = 'defaultName'
  //参数修饰符 使用了参数修饰符,该类中就有该只读成员变量,不用定义即可访问
  //只有类中的构造函数可以修改readonly只读属性 其他地方均不可以修改
  constructor (readonly name: string = 'defaultName') {
    this.name = name
    //可以成功修改,意义不大
    this.name = '我被修改了'
  }

}

const person: Person = new Person('lisa')

public 公共的

在任何地方都可以使用 class类中默认是public修饰符

class Person {
  //定义变量 需明确赋值
  public name: string = 'lisa'

  //定义对象 
  public obj = {
    name: 'lisa summer'
    age: 19
  }

  //定义方法  
  public fullName () {

  }
}

protected 受保护的

只能在本类或者是继承的派生类中使用

class Person {
  //只能在本类和派生类使用  
  protected name: string = 'lisa'
}

class Derived extends Person {
  construstor (name: string) {
    super(name)
  }
}

const person: Person = new Person()
const derived: Derived = new Derived()
console.log(deriver.name) // error

private 私有的

只能在本类中使用, 派生类 其他类 和类外部都不能使用

bug: 编译是提示错误 但可以正常访问 加上 as any时也可以获取到

用 #变量代替private 在es2020中使用私有属性#时ts转成js时会将#私有属性编译成weakMap来编译成js

class Person {
  private name: string = 'summer'
  #firstName: string = 'lisa'
}

class Derived extends Person {
  construotr () {
    super()
  }
}

const person: Person = new Person()
const derived: Person = new Derived()

console.log(derive.name) //编译是提示错误 但浏览器正常输出值 summer
console.log((derive as any).name) // 编译正常且不报错
console.log(derived.firstName) // 编译报错 输出undefined

static 静态成员

可直接使用 类名 . 静态成员来访问静态成员

类的constructor构造器不可以使用static静态前缀

静态成员不可以通过constructor构造器的this来访问

class Person {
  static constructor () {} //error
  static name: string = 'lisa'

  public constructor () {
    this.name = name //error
  }

  static add (num1: number, num2: number): number {
    return num1 + num2
  }
}

console.log(Person.name) //lisa
console.log(Person.add(1, 2)) // 3