【TypeScript】Re01

参考视频:

https://www.bilibili.com/video/BV14Z4y1u7pi

 

JS已有类型:

基础类型 number / string / boolean / null / undefined / symbol 
对象类型 object (数组,对象, 函数)

TS类型:

1、联合类型
2、类型别名
3、接口
4、元组
5、字面量类型
6、枚举
7、void
8、any  

 

函数类型:

function add1(n1: number, n2: number): number {
    return num1 + num2
}
// 箭头函数可以在注解方法参数时指定参数类型和返回类型
const add2 = (n1: number, n2: number): number => n1 + n2
// 或者第二种,直接对变量注解方法类型
const add3: (n1: number, n2: number) => number
  = (n1, n2) => n1 + n2

// 函数无返回类型时注解为 void
function greet(name: string): void {
  console.log('hello', name)
}
// 或者这样写
const greet: (name: string) => void = name => console.log('hello', name)

// 可选参数, 一般放在必填参数的后面使用
function mySlice(start?: number, end?: number): void {
  console.log('起始索引', start, '结束索引', end)
}

 

对象类型:

let person: {
  name: string,
  age: number,
  sayHi(): void,
 greet(name: string): void
} = {
    name: 'jack',
    age: 19,
    sayHi(){},
   greet(){}
}
// 如果是注解成一行编写
let person: { name: string; age: number; sayHi(): void; greet(name: string): void; }

// 可选属性
function myAxios(config: { url: string; method?: string }) {}
myAxios(url: 'asdasdasd')

 

接口类型:

// 用于复用对象类型
interface IPerson = {
    name: string
    age: number
    sayHi(): void
}

let person: IPerson = {
    name: 'jack',
    age: 19,
    sayHi() {}
}

  

接口和类型别名的区别:

接口只能为对象指定类型
类型别名:包括对象类型,支持任意类型

interface IPerson = {
    name: string
    age: number
    sayHi(): void
}
type IPerson = {
    name: string
    age: number
    sayHi(): void
}
type NumStr = number | string 

 

接口继承:

// 接口继承,用于多余属性复用
interface Point2D { x: number; y: number }
interface Point3D { x: number; y: number; z: number } 

// x轴和y轴都冗余了,使用extends实现
interface Point2D { x: number; y: number }
interface Point3D extends Point2D { z: number } 

  

元组类型:

经纬度,长度固定2个

// 数组长度可以多个
let position: number[] = [39.5427, 116.1327]

// 元组固定两个元素
let point: [number, number] = [39.5427, 116.1327]

  

类型断言:

// 强制断言一个类型
const aLink = document.getElementById('link') as HTMLAnchorElement

// 语法2
const aLink = <HTMLAnchorElement>document.getElementById('link')

 

字面量类型:

// let是变量 值可以是任意字符, ts推测类型是string
let str1 = 'Hello TS'

// const是常量 值不能变化只能是hello ts 所以类型即为 hello ts
const str2 = 'Hello TS'

// 显示声明
let str1: string = 'Hello TS'
const str2: 'Hello TS' = 'Hello TS'

// 当变量定义常量值类型时,等效const
let age: 18 = 18

// 结合 联合类型处理,只能在已列出的几种常量中选择
function directionChangeTo(direction: 'up' | 'down' | 'left' | 'right') {
  console.log(direction)
}

 

枚举类型:

代替联合类型,更具体的表示入参选项
enum Direction {
    Up,
    Down,
    Left,
    Right
}

// 方法参数声明
function changeDirection(direction: Direction): void {
    console.log(direction)
}
// 箭头函数声明
const changeDirection2: (direction: Direction) => void = direction => {
    console.log(direction)
}
// 调用
changeDirection(Direction.Up)

// 枚举是存在默认值的(自增下标),支持自定义值
enum Direction { Up = 2, Down = 4, Left = 8, Right = 16 }

// 如果是字符串枚举,则没有自增迭代值了
enum Direction { Up = 'Up', Down = 'Down', Left = 'Left', Right = 'Right' }

 

any类型:

// 失去TS类型保护, 不再编译警告
let obj: any = { x: 0 }
obj.bar = 100
obj()
const n: number = obj

  

typeof 操作符

1、在类型上下文中引用变量或者属性的类型
根据已有变量获得该变量的类型描述
2、只能用来查询变量或属性的类型,无法查询其它形式的类型


// 不使用typeof 
let p = { x: 1, y: 2}
function formatPoint(point: { x: number; y: number }) {}
formatPoint(p)

// 使用typeof
function formatPoint(point: typeof p) {}

  
高级类型

- Class类
- 类型兼容性
- 交叉类型
- 泛型 + Keyof
- 索引签名 + 索引查询
- 映射类型

 

Class类-1 创建类和属性

// js 语法
class Person {}
const p = new Person()

// ts 创建类和属性
class Person {
  age: number
  gender = '男'

  // 构造器默认为类的类型
  constructor(age: number, gender: string) {
    this.age = age
    this.gender = gender
  }
}
const p = new Person(18, '男')

  

Class类-2 实例方法

// 实例方法
class Point {
  x = 1
  y = 2

  scale(n: number) {
    this.x *= n
    this.y *= n
  }
}
const p = new Point()
p.scale(10)

  

Class类-3 类的继承

// class的继承
class Animal {
  move() { console.log('Moving along') }
}

class Dog extends Animal {
  name = '二哈'
  bark() { console.log('汪') }
}
const dog = new Dog()
dog.move()
dog.bark()
console.log('旺旺')

  

Class类-4 接口的实现

// class 的实现
interface Singable {
  sing(): void
  name: string
}

class Person implements Singable {
  name = 'jack'
  sing() {
    console.log('13766~')
  }
}

const jack = new Person()
jack.name
jack.sing()

  

Class类-5 访问修饰符

// 访问修饰符 public -> protected -> private
// 默认可见性 public,即省略不写
class Animal {
  public move() {
    console.log('')
  }
}
// protected 仅对所在类和子类中可见(实例对象不可见)
class Animal {
  protected move() {
    console.log('Moving along')
  }
}
class Dog extends Animal {
  bark() {
    console.log('汪')
    this.move()
  }
}
// private 只在当前类中可见(实例对象及子类不可见)
// 编写规范, private 方法名称 使用双下划线修饰左右两边
class Animal {
  private __move__() {
    console.log('Moving along')
  }
  walk() {
    this.__move__()
  }
}
// readonly 只读修饰符,只读防止在构造函数之外对函数赋值,只能修饰属性,不能修饰方法
// 接口或者{}表示的对象类型也支持readonly修饰
class Person {
  readonly age: number = 18 // 提供一个默认值
  constructor(age: number) {
    this.age = age
  }
}

 

类型兼容问题:

// 类型兼容问题
类型系统:Structural Type System (结构化类型系统), Nominal Type System (标明类型系统)
TS用STS系统 Duck Typing 类型检查关注值本身的类型,如果对象具有相同形状,则类型相同

// Duck Typing 如果它走路像鸭子,声音像鸭子,样子也像鸭子,那他就是鸭子
// NTS标明类型系统 例如Java 即使字段属性一样,但是不是同类型,就不兼容(以接口方式进行兼容)

// 样例
class Point { x: number; y: number }
class Point2D { x: number; y: number }

const p: Point = new Point2D()

// Class以多兼容少
class Point { x: number; y: number }
class Point3D { x: number; y: number; z: number }
const p: Point = new Point3D()

// interface以多兼容少,同属性兼容
interface Point { x: number; y: number }
interface Point2D { x: number; y: number }
let p1: Point
let p2: Point2D = p1

interface Point3D { x: number; y: number; z: number }
let p3: Point3D
p2 = p3

// 如果class 和 interface 同属性,方法,一样兼容的

  

函数类型兼容:

// 函数兼容
// 参数个数,参数类型,返回值类型

// 1、参数个数兼容, 参数多的函数兼容参数少的函数
type Fun1 = (a: number) => void
type Fun2 = (a: number, b: number) => void
let fun1 = Fun1
let fun2 = Fun2 = fun1

// 2、方法样例, forEach自动推导函数参数个数和类型
const arr = [1, 2, 3]
arr.forEach(() => {})
arr.forEach(item => {})

3、参数类型兼容
interface Point { x: number; y: number }
interface Point3D { x: number; y: number; z: number }

type F2 = (p: Point2D) => void
type F3 = (p: Point3D) => void
let f2: F2
f3 = f2

4、返回值类型同理
type F7 = () => { name: string }
type F8 = () => { name: string; age: number }
let f7: F7
let f8: F8
f7 = f8

  

接口交叉类型:

类型组合在一起实现

// 交叉类型 交叉符& 联合两个接口的属性,成一个新的类型
interface Person { name: string }
interface Contact { phone: string }
type PersonContact = Person & Contact
let pc: PersonContact = {
  name: 'cloud9',
  phone: '13755684304'
}

  

交叉类型和继承的区别?

// 交叉类型 和 继承 的区别?
1、都是为了对象类型的组合
2、处理对象类型冲突的属性方式不一样
- extends 会触发冲突警告
- & 会将冲突类型进行联合

interface A { fn: (val: number) => string }
interface B extends A { fn: (val: string) => string } // 语法警告 fn类型冲突

interface A { fn: (val: number) => string }
interface B { fn: (val: string) => string }
type C = A & B
// fn: (val: string | number) => string 参数类型将被联合起来

  

 TS泛型:

TS 泛型处理:
function genericType<Type>(val: Type): Type {
  return val
}
const num = genericType<number>(10)
const str = genericType<string>('2334')
const bool = genericType<boolean>(true)

泛型约束:
// 1、可以约束泛型为具体类型数组  Array<Type> ?
function genericTypeConstraint<Type>(val: Type[]): Type[] {
  return val
}

// 2、可以指定为某一个类型的子类型
interface ILength { length: number } // 该泛型必须要拥有ILength具备的属性
function genericTypeConstraint<Type extends ILength>(val: Type): Type {
  console.log(val.length)
  return val
}

genericTypeConstraint([1, 2, 3])
genericTypeConstraint('123')
genericTypeConstraint({ length: 10, name: 'cloud9' })
 
// 3、支持添加多个泛型,泛型之间可以进行约束设置
function getProp<Type, Field extends keyof Type>(obj: Type, key: Field) {
  return obj[key]
}
let person = { name: 'jack', age: 18 }
getProp(person, 'name')
getProp(18, 'toFixed')
getProp('abc', 'split')
getProp([1, 2, 3], 'length')
getProp([1, 2, 3], 1)

// 4、接口与泛型的组合
interface IdFunc<Type> {
  id: (val: Type) => Type
  ids: () => Type[]
}
// 使用泛型时,需要指定泛型的具体类型
let obj: IdFunc<number> = {
  id(val) { return val },
  ids() { return [1, 3, 5] }
}

// 5、泛型工具类
Partial<Type> 创建一个Partial类型,该类型泛型的类型属性可选
Readonly<Type> 创建一个ReadOnly类型,该类型泛型的类型属性只读
Pick<Type, Keys> 创建一个Pick类型, 根据Keys类型返回一个新的对象
Record<Keys, Type> 创建一个Record类型,根据Keys和Type返回对象

  

索引类型:

// 索引类型签名:
interface AnyObject {
    // key表示键名占位符,可以命名其他名称
    // 约束键类型为string, 值类型为number
    [key: string]: number
}

let obj: AnyObject = {
    a: 1,
    b: 2
}

interface MyArray<T> {
    [idx: number]: T
}

let arr: MyArray<number> = [1, 3, 5]
arr[0]


// 映射类型, 只能再type中使用
type PropKeys = 'x' | 'y' | 'z'
type Type1 = { x: number, y: number, z: number }
type Type2 = { [Key in PropKeys]: number }

// 除了联合类型映射,还支持类型键集合映射
type Type3 = { x: number, y: number, z: number }
type Type4 = { [Key in keyof Type3]: number }

// 索引查询
type Type5 = { x: number, y: string, z: boolean }
type TypeX = Type5['x'] // number, 被查询的键名必须在该类型中存在,否则报错

// 联合查询 查询指定类型中具体某个索引的类型,或者是索引类型的联合
type Type6 = { x: number, y: string, z: boolean }
type TypeXwithY = Type6['x' | 'y'] // number | string
type Type6Union = Type6[keyof Type6] // number | string | boolean

  

类型声明文件:

TS两种文件类型:[***.ts | ****.d.ts]

两种文件的区别?
- ts 文件
  1、包含类型信息和执行逻辑
  2、可以编译为.js文件,然后执行代码
- d.ts 文件 (d代表declare)
  1、只包含类型信息的类型声明文件
  2、不会生成js文件,仅提供类型信息

d 类似Java的接口
定义 变量、对象类型、方法声明


用法:
- - - - - index.d.ts - - - - - 
type Props = {
  x: number
  y: number
}

export { Props }

// 或者直接 export 
export type Props = {
  x: number
  y: number
}

- - - - - index.ts - - - - - 
import { Props } from './index'

  

 

 ts.config.js 的配置声明:

https://www.bilibili.com/video/BV14Z4y1u7pi?p=79

  

  

posted @ 2024-01-17 19:09  emdzz  阅读(7)  评论(0编辑  收藏  举报