一文学会 TypeScript 语法

2020-10-29  本文已影响0人  阿畅_

Typescript 基本语法

概念

什么是强类型语言

什么是弱类型语言

静态类型语言

动态类型语言

安装

创建 tsconfig.json

编译

基本数据类型

ES6

TS 数据类型

基本数据类型的使用

boolean

let isBoolean: boolean = false
let arr: Array<number> = [1,2,3] // 这个数组只能是 number 类型
// arr 和 arr2 是等价的
let arr2: number[] = [1,2,3]
// 多种类型的 Array
let arr3: Array<number|string> = [1,2,3, '4']

数字

let num: number = 123
let hexLiteral: number = 0xf00d
let binaryLiteral: number = 0b1010
let octalLiteral: number = 0o744

字符串

let name: string = 'achang'
let name1: string = `Hello ${name}`

数组

let arr: Array<number> = [1,3,4]
let arr2: number[] = [1,3,4] // 必须是number类型
let arr3: Array<number|string> = [1,2,3, '4'] // 可以是number 或 string 类型

元组

// 不能添加元素
let tuple: [number, string] = [0, '1']
// 可以手动添加新元素,可以添加进去
tuple.push('1')
tuple[2] // 但是可添加不能访问

let x: [string, number]
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error

枚举

// 枚举
enum Direction {
  Up,
  Down,
  Left,
  Right
}
// 会从0索引开始取值
console.log(Direction.Up) // 0
console.log(Direction[0]) // Up
// 如果赋值
enum Direction2 {
  Up = 1,
  Down,
  Left,
  Right
}
// 后面的会依次递增 Down = 2
// 字符串枚举
// 常量枚举,编译时会直接赋值,节省空间
enum Direction3 {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT'
}
const value = 'UP'
if (value === Direction3.Up) {
  console.log('相等的')
}

Any

let notSure: any = 4
notSure = "maybe a string instead"
notSure = false

Void

// void 表示没有任何返回值的类型
let noReturn = () => {}
function warnUser(): void {
  console.log("This is my warning message")
}
let unusable: void = undefined
// void 0 --> undefined,

Null 和 Undefined

let u: undefined = undefined
let n: null = null
let num: number = null

Never

let err = () => {
  new Error()
}

函数 Function

基本使用

// 参数是 number,返回值也是 number
function add1(x: number, y: number): number {
  return x + y
}
let res = add(1,2)

可选参数和默认参数

function add2(x = 123, y?:number) {
  return x + y
}
add2()

扩展运算符 ... 参数不固定式,可选参数必须要放到必选后面

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

函数重载

// 函数的重载
function add4(...rest: number[]): number;
function add4(...rest: string[]): string;
function add4(...rest: any[]): any {
  let first = rest[0]
  if (typeof first === 'string') {
    return rest.join('')
  }
  if (typeof first === 'number') {
    return rest.reduce((p, c) => p + c)
  }
}
add4(1,2,3)

object

// 对象
let obj: {x: number, y: number} = { x: 1, y: 1}
obj.y = 1

interface 接口

interface LabelledValue {
  label: string
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label)
}
let myObj = {size: 10, label: "Size 10 Object"}
printLabel(myObj)

使用类型断言的方式

interface Result {
  data: List[]
}
function render(result: Result) {
  result.data.forEach((a) => console.log(a))
}
let result1 = {
  data: [
    { id: 1, name: 'A' }
  ]
}
render(<Result>{
  data: [
    { id: 2, name: 'A' }
  ]
})

可选属性

interface List {
  name: string;
  age?: number; // 可有可无
}

可索引类型

number 索引

interface StringArray {
  [index: number]: string;
}

let myArray: StringArray
myArray = ["Bob", "Fred"]

string 索引

interface StringNames {
  [x: string]: string
}

number 和 string 索引混用

interface StringArray {
  [x: string]: string;
  // name: number --> ❌ `name`的类型与索引类型返回值的类型不匹配
  [y: number]: string;
  // [y: number]: number; ❌ 数字索引类型“number”不能赋给字符串索引类型“string”。
}

函数类型的接口 interface

let add: (x: number, y: number) => number
interface Add {
  // 参数和返回值
  (x: number, y: number): number
}

类型别名的方式 type

type Add1 = (x: number, y:number) => number

let add: Add1 = (x, y)  => x + y

混合接口

// 混合接口
interface Lib {
  (): void;
  version: string;
  doSome(): void;
}
let lib: Lib = (() => {}) as Lib
lib.version = '1.0'
lib.doSomething = () => {}
function LibF() {
  let lib: Lib = (() => {

  }) as Lib
  lib.version = '1'
  lib.doSome = () => {}
  return lib
}

类 class

class Dog {
  // 私有化,函数不能调用,也不能继承
  // private constructor(name: string) {
  //   this.name = name
  // }
  // 函数不能被实例化,只能被继承
  // protected constructor(name: string) {
  //   this.name = name
  // }
  constructor(name: string) {
    this.name = name
  }
  name: string
  age?: numebr // 可选属性
  run() {}
  private call() {} // 私有属性 子类和实例不能调用
  protected pro() {} // 受保护成员, 不能被实例化,只能被继承
  // 只读属性 只读属性必须在声明时或构造函数里被初始化。
  readonly log: number = 4
  // 静态成员, 只能通过类名调用,不能实例调用,子类可以调用
  static food: string = 'bones'
}

继承 extends

class Husky extends Dog {
  // 构造函数加属性,public 将参数实例属性,声明和赋值合并至一处
  constructor(name: any, public color: string) {
    super(name)
    this.color = color
  }
  // color: string  
  sleep() {
    console.log('dog sleep')
  }
}

抽象类 abstract

子类实例化,可以调用父类的方法

// 抽象类
abstract class Animal1 {
  constructor() {
  }
  eat() {
    console.log('eat ==>')
  }
  // 抽象方法
  abstract sleep(): void
}

class Dog4 extends Animal1 {
  constructor() {
    super()
  }
  name: string
  sleep() {
    console.log('dog sleep')
  }
}

let dog2 = new Dog4()
dog2.eat() // 子类实例化,可以调用父类的方法
dog2.sleep()

抽象类实现多态

class Cat extends Animal1 {
  sleep() {
    console.log('car sleep')
  }
}
let cat = new Cat()

// 实现多态
let amimals: Animal1[] = [dog2, cat]
// 循环调用子类的方法
amimals.forEach(a => {
  a.sleep()
})
// 结果 --> dog sleep car sleep

this 实现链式调用

// 实现链式调用
class WorkFlow {
  step1() {
    return this
  }
  step2() {
    return this
  }
}
new WorkFlow().step1().step2()

// 还以用子类继承父类的方式
class MyWorkFlow extends WorkFlow {
  next() {
    return this
  }
}

new MyWorkFlow().next().step1().next().step2()

接口和类

基本概念

类实现接口的约束

interface Human {
  name: string
  eat(): void
}
class Asian implements Human {
  constructor(name: string) {
    this.name = name
  }
  name: string
  eat() {

  }
  // 类可以定义自己的属性
  sleep() {}
}

接口的继承

interface Human {
  name: string
  eat(): void
}
interface Man extends Human {
  run(): void
}

interface Child {
  cur(): void
}
// 继承多个接口
interface Boy extends Man, Child {
}
// 实现 Boy 的约束, 需要把所有的接口约束都加上
let boy: Boy = {
  run() {}, 
  name: '', 
  eat() {}, 
  cur() {}
}

接口继承类, 类继承接口

class Parent {
  state = 1
}
interface AutoInterface extends Parent {
  
}
// 实现 AutoInterface 的约束, 也就是 Parent 中的属性
class C1 implements AutoInterface {
  state = 1
}

// 这样直接继承了 Parent 的 state 属性
class Bus extends Parent implements AutoInterface {
  
}
const child = new Bus()
child.state

泛型

泛型约束函数

// 泛型
function log<T>(value: T): T {
  console.log(value)
  return value
}
// 两种调用方式
// 1 指定类型
log<string>('1')
log<number>(1)
// 2 使用类型推断,ts 会自动获取类型
log('1')

类型别名的方式

type Log = <T>(value: T) => T
let myLog: Log = log
const s = myLog<number>(1)

interface + 泛型

interface Log<T> {
  (value: T): T
} 
let myLog: Log<number> = log
myLog(1)
interface Log<T = string> {
  (value: T): T
} 
let myLog: Log = log
myLog('1')

泛型约束类

class Log3<T> {
  run(value: T) {
    console.log(value)
    return value
  }
}

// 不指定类型参数时,value 的值可以是任意类型的值
let log3 = new Log3()
log3.run('1')
// 指定类型参数
let log4 = new Log3<number>()
log4.run(1)

泛型继承接口

// 泛型 继承 接口
interface Length {
  length: number
}
function log2<T extends Length>(value: T): T {
  console.log(value, value.length)
  return value
}

log2([1])
log2('1')
// log2(1123) ❌

泛型的好处

上一篇下一篇

猜你喜欢

热点阅读