TypeScript

一、变量的定义

// 数字
const n1: number = 123;

// 布尔
const n2: boolean = true;

// 字符串
const n3: string = 'hello';

// null
const n4: null = null;

// undefined
const n5: undefined = undefined;

// 数组
const names1: Array<string> = ["abc","cba"];
const names2: string[] = ["abc","cba"];

// 对象
const info = {
    name: 'why',
    age: 18
}

// 符号
const title1 = Symbol("title");
const title2 = Symbol("title");
const sym =  {
    [title1]: "程序员",
    [title2]: "老师",
}
export {}

二、TS 新增的数据类型

1、any 和 unknown

unknown类型只能赋值给any和unknown类型

 any类型可以赋值给任意类型

function foo() {
  return "abc"
}
function bar() {
  return 123
}

// unknown类型只能赋值给any和unknown类型
// any类型可以赋值给任意类型

let flag = true
let result: any // 最好不要使用any
if (flag) {
  result = foo()
} else {
  result = bar()
}

let message: string = result
let num: number = result

console.log(result)

export {}

2、void

void 通常用来指定一个函数式没有返回值的,那么它的返回值就是void 类型

可以将null 和 undefined 赋值给void 类型,也就是函数可以返回null 和undefined

function sum(num1: number, num2: number) {
  console.log(num1 + num2)
}

sum(20, 30)
// sum("abc", "cba")

3、never

function foo(): never {
  // 死循环
  while(true) {

  }
}
function bar(): never {
  throw new Error()
}

// 封装一个核心函数
function handleMessage(message: string | number | boolean) {
  switch (typeof message) {
    case 'string':
      console.log("string处理方式处理message")
      break
    case 'number':
      console.log("number处理方式处理message")
      break
    case 'boolean':
      console.log("boolean处理方式处理message")
      break
    default:
      const check: never = message
  }
}

handleMessage("abc")
handleMessage(123)

// 张三
handleMessage(true)

4、tuple (元组)

// tuple元组: 多种元素的组合
// "why" 18 1.88

// 1.数组的弊端
const info: any[] = ["why", 18, 1.88]
const infoObj = {
  name: "why",
  age: 18,
  height: 1.88
}

const name = info[0]
console.log(name.length)

// 2.元组的特点
const info1: [string, number, number] = ["why", 18, 1.88]
const name1 = info[0]
console.log(name1.length)
const age = info[1]
console.log(age.length)

export {}
// 元组的应用场景
function useState<T>(state: T) {
  let currentState = state
  const changeState = (newState: T) => {
    currentState = newState
  }
  const tuple: [T, (newState: T) => void] = [currentState, changeState]
  return tuple
}

const [counter, setCounter] = useState(10);
setCounter(1000)
const [title, setTitle] = useState("abc")
const [flag, setFlag] = useState(true)

type MyFunction = () => void
const foo1: MyFunction = () => {}

三、TS类型补充

1、函数的参数和返回值类型

// 给参数加上类型注解: num1: number, num2: number
// 给返回值加上类型注释: (): number
// 在开发中,通常情况下可以不写返回值的类型(自动推导)
function sum(num1: number, num2: number) {
  return num1 + num2
}

2、匿名函数的参数类型

// 通常情况下, 在定义一个函数时, 都会给参数加上类型注解的
function foo(message: string) {}

const names = ["abc", "cba", "nba"]
// item根据上下文的环境推导出来的, 这个时候可以不添加类型注解
// 上下文中的函数: 可以不添加类型注解
names.forEach(function(item) {
  console.log(item.split(""))
})

3、对象类型

1、对象类型

// Point: x/y -> 对象类型
// {x: number, y: number}
function printPoint(point: {x: number, y: number}) {
  console.log(point.x);
  console.log(point.y)
}
printPoint({x: 123, y: 321})
export {}

2、可选类型

// Point: x/y/z -> 对象类型
// {x: number, y: number, z?: number}
function printPoint(point: {x: number, y: number, z?: number}) {
  console.log(point.x)
  console.log(point.y)
  console.log(point.z)   // undefined
}

printPoint({x: 123, y: 321})
printPoint({x: 123, y: 321, z: 111})

export {}

4、联合类型

// number|string 联合类型
function printID(id: number|string|boolean) {
  // 使用联合类型的值时, 需要特别的小心
  // narrow: 缩小
  if (typeof id === 'string') {
    // TypeScript帮助确定id一定是string类型
    console.log(id.toUpperCase())
  } else {
    console.log(id)
  }
}

printID(123)
printID("abc")
printID(true)

5、可选类型和联合类型的关系

message?: string   ->   undefined | string

// 让一个参数本身是可选的
// 一个参数一个可选类型的时候, 它其实类似于是这个参数是 类型|undefined 的联合类型
function foo1(message?: string) {
  console.log(message)
}
foo1()

function foo2(message: string|undefined) {
  console.log(message)
}
foo2(undefined)
export {}

6、类型别名

// type用于定义类型别名(type alias)
type IDType = string | number | boolean
type PointType = {
  x: number
  y: number
  z?: number
}
function printId(id: IDType) {}
function printPoint(point: PointType) {}

7、类型断言

// <img id="why"/>

// 1.类型断言 as
// 将范围广的类型缩小为具体的类型
const el = document.getElementById("why") as HTMLImageElement
el.src = "url地址"

// 2.另外案例: Person是Student的父类
class Person {}

class Student extends Person {
  studying() {}
}

function sayHello(p: Person) {
  (p as Student).studying()
}

const stu = new Student()
sayHello(stu)

// 3.了解: as any/unknown
const message = "Hello World"
const num: number = (message as unknown) as number
const num: number = (message as any) as number

8、非空类型断言

// message? -> undefined | string
function printMessageLength(message?: string) {
  // if (message) {
  //   console.log(message.length)
  // }
  // vue3源码
  console.log(message!.length)  
  // ! 表示message 一定有值时
}

printMessageLength("aaaa")
printMessageLength("hello world")

9、可选链

可选链操作符 ?.

当对象的属性不存在时,会短路,直接返回undefined,如果存在,才会继续执行

type Person = {
  name: string
  friend?: {
    name: string
    age?: number,
    girlFriend?: {
      name: string
    }
  }
}

const info: Person = {
  name: "why",
  friend: {
    name: "kobe",
    girlFriend: {
      name: "lily"
    }
  }
}


// 另外一个文件中
console.log(info.name)
// console.log(info.friend!.name)
console.log(info.friend?.name)
console.log(info.friend?.age)
console.log(info.friend?.girlFriend?.name)

// if (info.friend) {
//   console.log(info.friend.name)

//   if (info.friend.age) {
//     console.log(info.friend.age)
//   }
// }

 10、字面量类型和字面量推理

// "Hello World"也是可以作为类型的, 叫做字面量类型
const message: "Hello World" = "Hello World"
let num: 123 = 123
// num = 321

// 字面量类型的意义, 就是必须结合联合类型
type Alignment = 'left' | 'right' | 'center'
let align: Alignment = 'left'
align = 'right'
align = 'center'
// align = 'hehehehe'
//  字面量推理
// const info = {
//   name: "why",
//   age: 18
// }

// info.name = "kobe"

type Method = 'GET' | 'POST'
function request(url: string, method: Method) {}

type Request = {
  url: string,
  method: Method
}

const options = {
  url: "https://www.coderwhy.org/abc",
  method: "POST"
} as const

request(options.url, options.method)

四、运算符

1、!!

将其他类型 转成布尔类型

const message = "Hello World"

// const flag = Boolean(message)
// console.log(flag)  // true

const flag = !!message
console.log(flag)  // true

2、??

空值合并操作符

let message: string|null = "Hello World"

// 如果message 为null 或者是 undefined 时,则使用后面的默认值
const content = message ?? "你好啊, 李银河"
// const content = message ? message: "你好啊, 李银河"
console.log(content)

五、类型缩小

// 1.typeof 的类型缩小
type IDType = number | string
function printID(id: IDType) {
  if (typeof id === 'string') {
    console.log(id.toUpperCase())
  } else {
    console.log(id)
  }
}

// 2.平等的类型缩小 (=== == !== !=/switch)
type Direction = "left" | "right" | "top" | "bottom"
function printDirection(direction: Direction) {
  // 1.if判断
  if (direction === 'left') {
    console.log(direction)
  } 
  // 2.switch判断
  switch (direction) {
    case 'left':
      console.log(direction)
      break;
    default:
      console.log(direction)
  }
}

// 3.instanceof
function printTime(time: string | Date) {
  if (time instanceof Date) {
    console.log(time.toUTCString())
  } else {
    console.log(time)
  }
}

class Student {
  studying() {}
}
class Teacher {
  teaching() {}
}
function work(p: Student | Teacher) {
  if (p instanceof Student) {
    p.studying()
  } else {
    p.teaching()
  }
}

const stu = new Student()
work(stu)

// 4. in
type Fish = {
  swimming: () => void
}
type Dog = {
  running: () => void
}
function walk(animal: Fish | Dog) {
  if ('swimming' in animal) {
    animal.swimming()
  } else {
    animal.running()
  }
}
const fish: Fish = {
  swimming() {
    console.log("swimming")
  }
}
walk(fish)

六、函数类型

1、函数的类型

// 1.函数作为参数时, 在参数中如何编写类型
function foo() {}
type FooFnType = () => void
function bar(fn: FooFnType) {
  fn()
}
bar(foo)

// 2.定义常量时, 编写函数的类型
type AddFnType = (num1: number, num2: number) => number
const add: AddFnType = (a1: number, a2: number) => {
  return a1 + a2
}
function calc(n1: number, n2: number, fn: (num1: number, num2: number) => number) {
  return fn(n1, n2)
}

const result1 = calc(20, 30, function(a1, a2) {
  return a1 + a2
})
console.log(result1)

const result2 = calc(20, 30, function(a1, a2) {
  return a1 * a2
})
console.log(result2)

2、函数参数的可选类型

可选类型必须写在必选类型的后面

// 可选类型是必须写在必选类型的后面的
// y -> undefined | number
function foo(x: number, y?: number) {}
foo(20, 30)
foo(20)

3、函数参数的默认值

// 必传参数 - 有默认值的参数 - 可选参数
// 一般将有默认值的参数放到后面
function foo(y: number, x: number = 20) {
  console.log(x, y)
}
foo(30) 

// 当不传第一个参数时,需要指定为undefined
function foo(x: number = 20, y: number) {
  console.log(x, y)
}
foo(undefined, 20)

4、函数的剩余参数

// function sum(num1: number, num2: number) {
//   return num1 + num2
// }

function sum(initalNum: number, ...nums: number[]) {
  let total = initalNum
  for (const num in nums) {
    console.log("num", num)
  }
  return total
}

console.log(sum(20, 30))
console.log(sum(20, 30, 40))
console.log(sum(20, 30, 40, 50))

5、this 的默认推导

// this是可以被推导出来 info对象(TypeScript推导出来)
const info = {
  name: "why",
  eating() {
    console.log(this.name + " eating")
  }
}

info.eating()

6、this 的不明确类型

type ThisType = { name: string };
function eating(this: ThisType, message: string) {
  console.log(this.name + " eating", message);
}
const info = {
  name: "why",
  eating: eating,
};
// 隐式绑定
info.eating("哈哈哈");
// 显示绑定
eating.call({name: "kobe"}, "呵呵呵")
eating.apply({name: "james"}, ["嘿嘿嘿"])
export {};

7、函数的承载

1、联合类型出现的问题

/**
 * 通过联合类型有两个缺点:
 *  1.进行很多的逻辑判断(类型缩小)
 *  2.返回值的类型依然是不能确定
 */
function add(a1: number | string, a2: number | string) {
  if (typeof a1 === "number" && typeof a2 === "number") {
    return a1 + a2
  } else if (typeof a1 === "string" && typeof a2 === "string") {
    return a1 + a2
  }
  // return a1 + a2;
}
add(10, 20)

2、函数的重载

// 函数的重载: 函数的名称相同, 但是参数不同的几个函数, 就是函数的重载
// 函数的声明
function add(num1: number, num2: number): number; // 没函数体
function add(num1: string, num2: string): string;

// 函数的实现
function add(num1: any, num2: any): any {
  if (typeof num1 === 'string' && typeof num2 === 'string') {
    return num1.length + num2.length
  }
  return num1 + num2
}

const result = add(20, 30)
const result2 = add("abc", "cba")
console.log(result)
console.log(result2)

// 在函数的重载中, 实现函数是不能直接被调用的
// add({name: "why"}, {age: 18})

export {}

3、函数重载的练习

// 实现方式一: 联合类型
function getLength(args: string | any[]) {
  return args.length
}
console.log(getLength("abc"))
console.log(getLength([123, 321, 123]))

// 实现方式二: 函数的重载
// function getLength(args: string): number;
// function getLength(args: any[]): number;

// function getLength(args: any): number {
//   return args.length
// }
// console.log(getLength("abc"))
// console.log(getLength([123, 321, 123]))

七、类的使用

1、类的定义

class Person {
  name: string
  age: number

  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }

  eating() {
    console.log(this.name + " eating")
  }
}

const p = new Person("why", 18)
console.log(p.name)
console.log(p.age)
p.eating()

2、类的继承

class Person {
  name: string = ""
  age: number = 0

  eating() {
    console.log("eating")
  }
}

class Student extends Person {
  sno: number = 0

  studying() {
    console.log("studying")
  }
}

class Teacher extends Person {
  title: string = ""

  teaching() {
    console.log("teaching")
  }
}

const stu = new Student()
stu.name = "coderwhy"
stu.age = 10
console.log(stu.name)
console.log(stu.age)
stu.eating()
class Person {
  name: string
  age: number
  // 构造器
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }

  eating() {
    console.log("eating 100行")
  }
}

class Student extends Person {
  sno: number

  constructor(name: string, age: number, sno: number) {
    // super调用父类的构造器
    super(name, age)
    this.sno = sno
  }

  eating() {
    console.log("student eating")
    super.eating()
  }

  studying() {
    console.log("studying")
  }
}

const stu = new Student("why", 18, 111)
console.log(stu.name)
console.log(stu.age)
console.log(stu.sno)

stu.eating()

3、类的多态

class Animal {
  action() {
    console.log("animal action")
  }
}

class Dog extends Animal {
  action() {
    console.log("dog running!!!")
  }
}

class Fish extends Animal {
  action() {
    console.log("fish swimming")
  }
}

// 多态:父类引用(类型)指向子类对象
// animal: dog/fish
// 多态的目的是为了写出更加具备通用性的代码
function makeActions(animals: Animal[]) {
  animals.forEach(animal => {
    animal.action()
  })  
}

makeActions([new Dog(), new Fish()])

4、类的成员修饰符

1、public

修饰的是在任何地方可见、公有的属性或方法,默认编写的属性就是public

2、private

修饰的仅是同一类中可见、私有的属性或方法

class Person {
  private name: string = ""

  // 封装了两个方法, 通过方法来访问name
  getName() {
    return this.name
  }

  setName(newName) {
    this.name = newName
  }
}

const p = new Person()
console.log(p.getName())
p.setName("why")

3、prrotected

修饰的是仅在类自身及子类中可见、受保护的属性或方法

// protected: 在类内部和子类中可以访问

class Person {
  protected name: string = "123"
}

class Student extends Person {
  getName() {
    return this.name
  }
}

const stu = new Student()
console.log(stu.getName())

5、只读属性_readonly

class Person {
  // 1.只读属性是可以在构造器中赋值, 赋值之后就不可以修改
  // 2.属性本身不能进行修改, 但是如果它是对象类型, 对象中的属性是可以修改
  readonly name: string
  age?: number
  readonly friend?: Person
  constructor(name: string, friend?: Person) {
    this.name = name
    this.friend = friend
  }
}

const p = new Person("why", new Person("kobe"))
console.log(p.name)
console.log(p.friend)

// 不可以直接修改friend
// p.friend = new Person("james")
if (p.friend) {
  p.friend.age = 30
} 

// p.name = "123"

6、类的访问器:getters-setters

class Person {
  private _name: string
  constructor(name: string) {
    this._name = name
  }

  // 访问器setter/getter
  // setter
  set name(newName) {
    this._name = newName
  }
  // getter
  get name() {
    return this._name
  }
}

const p = new Person("why")
p.name = "coderwhy"
console.log(p.name)

7、类的静态成员

// class Person {
//   name: string = ""
//   age: number = 12
// }

// const p = new Person()
// p.name = "123"

class Student {
  static time: string = "20:00"

  static attendClass() {
    console.log("去学习~")
  }
}

console.log(Student.time)
Student.attendClass()

8、抽象类

抽象类是不能实例化的(也就是不能通过new 创建)

抽象方法必须被子类实现,否则该类必须是一个抽象类

function makeArea(shape: Shape) {
  return shape.getArea()
}

// 抽象类中的抽象方法必须被子类实现
abstract class Shape {
  abstract getArea(): number
}

class Rectangle extends Shape {
  private width: number
  private height: number

  constructor(width: number, height: number) {
    super()
    this.width = width
    this.height = height
  }

  getArea() {
    return this.width * this.height
  }
}

class Circle extends Shape {
  private r: number

  constructor(r: number) {
    super()
    this.r = r
  }

  getArea() {
    return this.r * this.r * 3.14
  }
}

const rectangle = new Rectangle(20, 30)
const circle = new Circle(10)

console.log(makeArea(rectangle))
console.log(makeArea(circle))
// makeArea(new Shape())

// makeArea(123)
// makeArea("123")

9、类的类型

class Person {
  name: string = "123"
  eating() {

  }
}

const p = new Person()

const p1: Person = {
  name: "why",
  eating() {

  }
}

function printPerson(p: Person) {
  console.log(p.name)
}

printPerson(new Person())
printPerson({name: "kobe", eating: function() {}})

八、接口的使用

1、声明对象类型

// 通过类型(type)别名来声明对象类型
// type InfoType = {name: string, age: number}

// 另外一种方式声明对象类型: 接口interface
// 在其中可以定义可选类型
// 也可以定义只读属性
interface IInfoType {
  readonly name: string
  age: number
  friend?: {
    name: string
  }
}

const info: IInfoType = {
  name: "why",
  age: 18,
  friend: {
    name: "kobe"
  }
}

console.log(info.friend?.name)
console.log(info.name)
// info.name = "123"
info.age = 20

2、索引类型

// 通过interface来定义索引类型
interface IndexLanguage {
  [index: number]: string
}

const frontLanguage: IndexLanguage = {
  0: "HTML",
  1: "CSS",
  2: "JavaScript",
  3: "Vue"
}


interface ILanguageYear {
  [name: string]: number
}

const languageYear: ILanguageYear = {
  "C": 1972,
  "Java": 1995,
  "JavaScript": 1996,
  "TypeScript": 2014
}

3、函数类型

// type CalcFn = (n1: number, n2: number) => number
// 可调用的接口
interface CalcFn {
  (n1: number, n2: number): number
}

function calc(num1: number, num2: number, calcFn: CalcFn) {
  return calcFn(num1, num2)
}

const add: CalcFn = (num1, num2) => {
  return num1 + num2
}

calc(20, 30, add)

4、接口的继承

interface ISwim {
  swimming: () => void
}

interface IFly {
  flying: () => void
}

// 接口实现多继承
interface IAction extends ISwim, IFly {

}

const action: IAction = {
  swimming() {

  },
  flying() {
    
  }
}

5、交叉类型

// 一种组合类型的方式: 联合类型
type WhyType = number | string
type Direction = "left" | "right" | "center"

// 另一种组件类型的方式: 交叉类型
type WType = number & string

interface ISwim {
  swimming: () => void
}

interface IFly {
  flying: () => void
}

type MyType1 = ISwim | IFly
type MyType2 = ISwim & IFly

const obj1: MyType1 = {
  flying() {

  }
}

const obj2: MyType2 = {
  swimming() {

  },
  flying() {
    
  }
}

6、接口的实现

interface ISwim {
  swimming: () => void
}

interface IEat {
  eating: () => void
}

// 类实现接口
class Animal {}

// 继承: 只能实现单继承
// 实现: 实现接口, 类可以实现多个接口
class Fish extends Animal implements ISwim, IEat {
  swimming() {
    console.log("Fish Swmming")
  }
  eating() {
    console.log("Fish Eating")
  }
}


class Person implements ISwim {
  swimming() {
    console.log("Person Swimming")
  }
}

// 编写一些公共的API: 面向接口编程
function swimAction(swimable: ISwim) {
  swimable.swimming()
}

// 1.所有实现了接口的类对应的对象, 都是可以传入
swimAction(new Fish())
swimAction(new Person())

swimAction({swimming: function() {}})

7、interface 和 type 的区别

如果是定义非对象类型,建议使用type

如果是定义对象类型,他们是有区别的:

        1.interface 可以重复的对某个接口来定义属性和方法

        2.而type 定义的是别名,别名是不能重复的

interface IFoo {
  name: string
}
interface IFoo {
  age: number
}
// interface IFoo {
//   name: string
//   age: number
// }

// 同名的接口,里面的属性是合并关系
const foo: IFoo = {
  name: "why",
  age: 18
}

document.getElementById("app") as HTMLDivElement
window.addEventListener

interface Window {
  age: number
}
window.age = 19
console.log(window.age)

// type 不能定义名字重复的类型
type IBar = {
  name: string
}
// type IBar = {
//   age: number
// }

8、字面量赋值

interface IPerson {
  name: string
  age: number
  height: number
}

const info = {
  name: "why",
  age: 18,
  height: 1.88,
  address: "广州市"
}

// freshness擦除
const p: IPerson = info
console.log(info)
console.log(p) 


function printInfo(person: IPerson) {
  console.log(person)
}

// 代码会报错
// printInfo({
//   name: "why",
//   age: 18,
//   height: 1.88,
//   address: "广州市"
// })

const info = {
  name: "why",
  age: 18,
  height: 1.88,
  address: "广州市"
}

printInfo(info)

九、枚举类型

// type Direction = "left" | "Right" | "Top" | "Bottom"
enum Direction {
  LEFT = "LEFT",  // 默认是 0
  RIGHT = "RIGHT",  // 默认是 1
  TOP = "TOP",  // 默认是 2
  BOTTOM = "BOTTOM"  // 默认是 3
}

// let name: string = "abc"
// let d: Direction = Direction.BOTTOM

function turnDirection(direction: Direction) {
  console.log(direction)
  switch (direction) {
    case Direction.LEFT:
      console.log("改变角色的方向向左")
      break;
    case Direction.RIGHT:
      console.log("改变角色的方向向右")
      break;
    case Direction.TOP:
      console.log("改变角色的方向向上")
      break;
    case Direction.BOTTOM:
      console.log("改变角色的方向向下")
      break;
    default:
      const foo: never = direction;
      break;
  }
}

turnDirection(Direction.LEFT)
turnDirection(Direction.RIGHT)
turnDirection(Direction.TOP)
turnDirection(Direction.BOTTOM)

十、泛型

T: Type 的缩写, 类型

K、V: key 和 value 的缩写, 键值对

E:Element 的缩写,元素

O: Object 的缩写,对象

1、泛型的使用

// 类型的参数化
// 在定义这个函数时, 我不决定这些参数的类型
// 而是让调用者以参数的形式告知,我这里的函数参数应该是什么类型
function sum<Type>(num: Type): Type {
  return num
}

// 1.调用方式一: 明确的传入类型
sum<number>(20)
sum<{name: string}>({name: "why"})
sum<any[]>(["abc"])

// 2.调用方式二: 类型推到
sum(50)
sum("abc")

2、泛型接收多个参数

function foo<T, E, O>(arg1: T, arg2: E, arg3?: O, ...args: T[]) {
    console.log(arg1, arg2, arg3, args)
}
foo<number, string, boolean>(10, "abc", true, 100, 200, 300)

3、泛型接口的使用

interface IPerson<T1, T2> {
  name: T1
  age: T2
}
const p: IPerson<string, number> = {
  name: "why",
  age: 18
}


interface IPerson<T1=string, T2=number> {
  name: T1
  age: T2
}
const p: IPerson= {
  name: "why",
  age: 18
}

4、泛型类的使用

class Point<T> {
  x: T
  y: T
  z: T

  constructor(x: T, y: T, z: T) {
    this.x = x
    this.y = y
    this.z = z
  }
}

const p1 = new Point("1.33.2", "2.22.3", "4.22.1")
const p2 = new Point<string>("1.33.2", "2.22.3", "4.22.1")
const p3: Point<string> = new Point("1.33.2", "2.22.3", "4.22.1")

const names1: string[] = ["abc", "cba", "nba"]
const names2: Array<string> = ["abc", "cba", "nba"] // 不推荐(react jsx <>)

5、泛型的类型约束

interface ILength {
  length: number
}

function getLength<T extends ILength>(arg: T) {
  return arg.length
}

getLength("abc")
getLength(["abc", "cba"])
getLength({length: 100})

6、非空判断运算符

const flag = "" ?? true
console.log(flag)

十一、ts 补充

1、命名空间

// format.ts
export namespace time {
  export function format(time: string) {
    return "2222-02-22"
  }

  export function foo() {

  }

  export let name: string = "abc"
}

export namespace price {
  export function format(price: number) {
    return "99.99"
  }
}


// main.ts
import { time, price } from './utils/format'
console.log(time.format("11111111"))
console.log(price.format(123))

2、模块和声明

// 声明模块
declare module 'lodash' {
  export function join(arr: any[]): void
}

// 声明变量/函数/类
declare let whyName: string
declare let whyAge: number
declare let whyHeight: number

declare function whyFoo(): void

declare class Person {
  name: string
  age: number
  constructor(name: string, age: number)
}

// 声明文件
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.png'
declare module '*.svg'
declare module '*.gif'

// 声明命名空间
declare namespace $ {
  export function ajax(settings: any): any
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值