likes
comments
collection
share

你需要知道的TypeScript(基础类型、接口)

作者站长头像
站长
· 阅读数 12

前言

随着时间的推移,typeScript 已经成为现在前端必备的技能,但是由于一些项目历史原因,可能还并不能及时用上这门技术。但是对于个人能力的提升来说,这个又是当下必须要会的以应该学习它为编码保驾护航。

基础数据类型定义

布尔值

const isBool: boolean = false

数字

const num: number = 1

字符串

const str: string = 'water'

空值不返回值

function func(): void {
  console.log('water')
}

null、undefined

与 void 的区别是 undefined 和 null 是所有类型的子类型。就是说可以赋值给任何类型

const num: number = undefined
const str: string = null

// 以下使用方式会报错
let v: void
const num: number = v

任意值

使用 any 表示可以赋任意的值

const str: string = 'water'
const num: number = 12

在任意值上访问任何属性和方法都是可以的

const anyStr: any = 'water'
console.log(anyStr.name)

const anyFuncStr: any = 'func'
anyFuncStr.getName()

Never

never 类型表示的是那些永不存在的值的类型。 例如, never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never 类型,当它们被永不为真的类型保护所约束时。 never 类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是 never 的子类型或可以赋值给 never 类型(除了 never 本身之外)。 即使 any 也不可以赋值给 never。

// 返回never的函数
function error(message: string): never {
  throw new Error(message)
}
// 推断的返回值类型never
function fail() {
  return error('water fail')
}

// 返回never的函数必须存在无法到达的终点
function func(): never {
  while (true) {}
}

数组

数组的定义有两种方式,如下

const arr: number[] = [1, 2, 3]
const arr: Array<number> = [1, 2, 3]

元组

const arr: [string, number] = ['water', 20]

当元组被访问一个越界的元素的时候,会使用联合类型替代

const arr: [string, number] = ['water', 20]

// 不报错,字符串可以赋值给(string | number)类型
arr[3] = 'blog'

// 不报错,'string' 和 'number' 都有toString方法
x[4].toString()

// err,布尔值不是(string | number)类型
x[6] = true

枚举

enum Color {
  Red,
  Green,
  Blue,
}

const c: Color = Color.Red

// 也可以改变初始值
enum Color {
  Red = 1,
  Green,
  Blue,
}

// 也可以全部自定义
enum Color {
  Red = 1,
  Green = 3,
  Blue = 4,
}

对象

const obj: { a: number } = { a: 1 }

类型断言

// 尖括号语法
const str: any = 'water'

const len: number = (<string>str).length

// as语法

const len: number = (str as string).length

接口

接口就像一个名字。来描述一个变量的要求或者规则。类型检查不会检查顺序,只要属性存在和类型正确就可以了

interface Water {
  name: string
}

const water: Water = { name: 'water' }

可选属性

可选属性就是可以存在,也可以不存在。

interface Water {
  name?: string
  age?: number
}

只读属性

属性只可读,不可以更改重新赋值

interface Water {
  readonly name: string
  readonly age: number
}

const water: Water = { name: 'water', age: 18 }

// 会报错
water.age = 28

readonly vs const

来判断该用 readonly 还是 const 的最简单的方法就是看它是作为变量使用还是作为一个属性。作为变量使用的化就用 const,如果作为属性就使用 readonly

定义带有任何属性

interface Water {
  name?: string
  age?: number
  [propName: string]: any
}

//问题是会绕开额外的属性检查
const water = { namee: 'water', width: 100 }

用接口定义函数类型

interface Func {
  (name: string, age: number): string
}

let func: Func

func = function (name: string, age: number) {
  return name + age
}

用接口定义带索引的类型(类似数组)

TypeScript 支持两种索引签名:字符串和数字,可以同时使用两种类型的索引。但是数字索引的返回值必须是字符串索引返回值类型的子类型,这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。

class Animal {
  name: string
}

class Dog extends Animal {
  color: string
}

// 报错:使用数值型的索引的返回值不是使用字符串索引的返回值的子类
interface Err {
  [x: number]: Animal
  [x: string]: Dog
}
// ok

interface Ok {
  [x: number]: Dog
  [x: string]: Animal
}

类类型

实现接口

interface Person {
    name:string
}

class Water implements Person {
  name:string
  constructor(age:number)
}

类静态部分和实例部分

interface WaterConstructor {
  new(name:string,age:number):WaterInterface
}

interface WaterInterface {
  run()
}
function createWater(ctor:WaterConstructor,name:string,age:number):WaterInterface {
  return new ctor(name,age)
}

class OneWater implements WaterInterface {
  constructor(name:string,age:number){}
  run () {
    console.log('one run')
  }
}

class TwoWater implements WaterInterface {
  constructor(name:string,age:number){}
  run(){
    console.log('two run')
  }
}

const oneWater = createWater(OneWater,'water1',18)
const twoWater = createWater(TwoWater,'water2',28)

继承接口

interface Person {
  name:string
}

interface Water extends Person {
  age:number
}

let water = <Water>{}
water.name = "water"
water.age = 18

// 继承多个接口
interface Person {
  name: string
}

interface Water {
  age:number
}

interface IWater extends Person,Water {
  height:number
}

let water = <IWater>{}
water.name='water'
water.age=18
water.height=175

接口继承类

class Person {
    private name: string;
}

interface Water extends Person {
    run(): void;
}

class Button extends Person implements Water {
    run() { }
}

class TextBox extends Person {
    run() { }
}

// 错误:“CWater”类型缺少“name”属性。
class CWater implements Water {
    run() { }
}

小结

总结了一些基础类型定义的使用方法,接下来再整理下其他的一些基础知识与用法。内容较多,分多次整理。

转载自:https://juejin.cn/post/7180944389504499768
评论
请登录