TypeScript基础

数据类型

typescript会进行类型推导,不需要每个都写类型注释

数组

let list1:string[]=['aa','bb']  // 数组类型并且内容都为string
let list2:any[] = ['aa',1,3]
let list3:Array<string> = ['aa','aa2','bb']

枚举

enum Dict {
  UP=1<<1,  // 默认=0
  Down=1<<2,
  LEFT,
  RIGHT='ddd'
}

const d1: Dict = Dict.UP

Object类型

type infoType = {
    name:string
    age:number
    y  // 任意类型
    x?: number // 可选
 
}
let info:infoType = {
    name:'ss',
    age:33,
    y:2,
    
}

let info2:Object = {  // info2.name 报错 Object表示一个空对象
    name:'ss',
    age:33
}

Symbol类型

const s:symbol = Symbol('aaa')

null和undefined

let a:null = null
let b:undefined = undefined

string

let s:string = 'aaa'

函数类型

type infoType = {
    name:string
    age:number
  	
}
// 剩余参数类型 (...arg:number)
function foo(name:string,...arg:number[]): infoType[] {
    let info:infoType[] = []
    info.push({name:'ss',age:33})
    return info
}

匿名函数不需要进行类型注释,根据上下文会自动指定

any

let a:any = ''
a=3
console.log(a.length)  

unknown

与any的区别:

  • unknown类型进行任何操作都是不合法的

  • any类型任何操作都是合法的

  • unknown类型必须进行校验

let a:unknow = ''
console.log(a.length)  // 报错

// unknow类型必须进行校验, 类型缩小
if (typeof a === 'string') {
	console.log(a.length)
}

void

指定一个函数没有返回值

function foo():void {
    return undefined  // 允许void类型返回undefined
}
type FnType = ()=>void
function foo(fn:FnType):void {
    fn()
    return undefined  // 允许void类型返回undefined
}

// type FooType = (name:string)=>infoType[]
function foo(name:string): infoType[] {
    let info:infoType[] = []
    info.push({name:'ss',age:33})
    return info
}

never

表示的是那些永不存在的值的类型

// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
    throw new Error(message);
}

// 推断的返回值类型为never
function fail() {
    return error("Something failed");
}

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

元组

已知元素数量和类型的数组,各元素的类型不必相同

数组类型应该是同一类型

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

联合类型

联合成员,二个及以上

let s:string | number = ''

交叉类型

并集

let s:IPointType & IPointType2

类型别名

type 关键字

type MyType = number | string

function printID(id:MyType){
    console.log(id)
}

接口别名

interface 关键字

interface PointType {
    x: number
    y: number
    z?:number
}
// 可以多次声明
interface PointType {
    name: string
}
    
// 继承
interface PointType2 extends PointType{
    age:number
}
function foo(point:PointType){
    
}

与type区别

  1. 在定义对象类型时,大部分情况都可使用
  2. type的使用范围更广,interface 只能声明对象
  3. interface 可以多次声明, type不允许相同的别名存在
  4. interface 支持继承

类型断言

const imgEl = document.querySelector('.img') 
// 不确定imgEl 是什么对象时
 imgEL.src  // imgEl不是HTMLImageElement时报错

// 类型断言:确定类型时使用
const imgEl = document.querySelector('.img')  as HTMLImageElement

as 关键字

断言规则:

  • 更加具体的类型
  • 不太具体类型: any 、unkown

非空类型断言:?!

info.obj?.name

info.obj!.name='xxx' obj强制不为空,危险

字面量

const name:'hyf' | 'aa' | '3' = '3'

调用签名

函数可被调用,并且有其他属性

与 type 定义的区别: type 不包含其他属性

interface ICallBack {
    name:string;
    age:number;
    (dir:string):string   // type xxx = (dir:string)=>string
}
const callback: ICallBack = (dir:string):string=>{
    return dir
}

构造签名

class Person {
    
}
interface Iclass {
    new ():Person
}

函数的重载

// 函数重载签名
function foo(arg:number,arg2:number):number
function foo(arg:string,arg2:string):string

// 通用函数实现
function foo(arg:any,arg2:any):any{
    return arg+arg2
}

this

默认是any类型

tsconfig.json

noImplicitThis: 是否允许模糊的this

内置工具

ThisParameterType

// 提取函数中this类型
type FooType = typeof foo

type FooThisType = ThisParameterType<FooType>

OmitThisParameter

过滤this

// 省略this,
type PureFooType = OmitThisParameter<FooType>

ThisType

绑定一个上下文的this

interface ISate {
	name:string
}

interface IState{
	state:ISate
    eating:()=>void
}
// & ThisType<ISate> 绑定this 上下文
const store:IState & ThisType<ISate> {
	...
    eating(){
    	console.log(this.name)
	}
}

Partial

把一个对象中类型转为可选

interface IT{
	name:string
}

//使用
type ITOption = Partial<IT>  // name?:string
    
    
// 实现
type HYPartial<T> = {
	[P in keyof T]?:T[P]
}

Required

把一个对象中类型转为必选

interface IT{
	name?:string,
    age:number
}

//使用
type ITOption = Required<IT>  // name:string;age:number
// 实现
type HYRequired<T> = {
	[P in keyof T]-?:T[P]
}

Readonly

把一个对象中类型转为只读

interface IT{
	name?:string,
    age:number
}

//使用
type ITOption = Readonly<IT>  // readonly name:string; readonly age:number
// 实现
type HYReadonly<T> = {
	readonly [P in keyof T]:T[P]
}

Record<keyType,valueType>


interface IT{
	name?:string,
    age:number
}
type t1 = 'aaa'|'ddd'|'ccc'
//使用
type ITOption = Record<t1,IT>   // key的类型必须是t1, value的类型必须是t2

const option:ITOption = {
    aaa:{
        name:'xxx',
    	age:22
    },
    ddd:{
        age:22
    }
}
type Res = keyof any // number|string|symbol
// 实现
type HYRecord<Keys extends keyof any,T> = {
	[P in keyof Keys]:T
}
  1. t1是一个联合类型
  2. 确保t1 是一个可以作为key的联合类型: <Keys extends keyof any,T>

Pick<Type,Keys>

挑选出 类型 组成新的类型

interface IT{
	name?:string
    age:number
    height:number
}

// 选出age,height
type ITOption = Pick<IT,'height'|'age'>
    
// 实现
type HYPick<T,K extends keyof T> = {
	[P in K]:T[P]
}

Omit<Type,Keys>

过滤属性

interface IT{
	name?:string
    age:number
    height:number
}

// 去除age,height
type ITOption = Pick<IT,'height'|'age'>  // name?:string
    
// 实现
type HYOmit<T,K extends keyof T> = {
    // 判断P 是否存在于 K中 存在 never 否则 返回对应P(属性)
	[P in keyof T as P extends K? never:P ]:T[P]
}

Exclude

联合类型中 排除掉

type MYType = 'aaa' | 'bbb' | 'ccc'

type ITOption = Exclude<MYType,'aaa'>  // 'bbb'|'ccc'

type HYExclude<T,E> = T extends E? never:T

Extract

联合类型中提取

type MYType = 'aaa' | 'bbb' | 'ccc'

type ITOption = Extract<MYType,'aaa'|'bbb'>  // 'aaa'|'bbb'

type HYExtract<T,E> = T extends E? T : never

NonNullable

排除所有null/undefined类型

type MYType = 'aaa' | 'bbb' | 'ccc' | null | undefined

type ITOption = NonNullable<MYType>  // 'aaa' | 'bbb' | 'ccc'

type HYNonNullable<T> = T extends null|undefined? never :T 

ReturnType

获取一个函数的返回值类型

// 获取一个函数的返回值类型
type CallFn = (arg1:number,arg2:number2) => number
function foo(){
    return 'foo'
}

type CallReturnType = ReturnType<CallFn>   // number
type FooReturnType = ReturnType<typeof foo>  // string
    
type HYReturnType<T> = 
// 必须是函数类型 限制类型  extends  (...args:any) => any
// 第二个extends表示  T 属于 xxx类型吗?
// 加上推断infer 
type HYReturnType<T extends (...args:any) => any > = T extends (...args:any) => infer R? R:never

InstanceType

所有构造函数的实例的类型

class Person1 {
  constructor(){

  }
}

// 区别 typeof Person 和 Person
// typeof Person 构造函数具体类型
function factory<T extends new (...arg:any[])=>any>(ctor:T):T{
  return new ctor()
}
const a = factory(Person) // function factory<typeof Person>(ctor: typeof Person): typeof Person

// InstanceType 构造函数创建出来实例对象的具体类型  Person
function factory2<T extends new (...arg:any[])=>any>(ctor:T):InstanceType<T>{}
  return new ctor()
}
const a1 = factory2(Person) // function factory<typeof Person>(ctor: typeof Person): Person


type HYInstanceType<T extends new (...args:any) => any > = T extends new (...args:any) => infer R? R:never

类的使用

class Person {
  // 严格模式下,需要初始化,可以使用name!:string的语法不初始化,
  name!: string  
  age: number
  constructor(name:string,age:number){
    this.name = name
    this.age = age
  }

  eating(){

  }
}

// 语法糖 ,同名参数可以在construct函数中 在参数前加上修饰符表示
class Person {
  
  // name: string  
  // age: number
  constructor(public name:string, private age:number){
    this.name = name
    this.age = age
  }

  eating(){

  }
}

public

公共的,默认就是public

private

私有的, 只在类的内部访问

protected

只在类及子类中使用,受保护的属性和方法

readonly

只读属性,不能写入

getter/setter

如果有私有属性需要给到外界,可以使用getter、setter

抽象类 abstract

abstract class Person {
  // 只声明没有实现体
  // 不能实例化
  // 抽象方法必须存在抽象类中
  abstract eating()
}

class Child1 extends Person {
  // 子类必须实现 eating
  eating(){
    console.log(1)
  }
}

class Child2 extends Person {
  // 子类必须实现 eating
  eating(){
    console.log(2)
  }
}

function foo(shap:Person){
  shap.eating()
}

foo(new Child1())
foo(new Child2())

索引签名

interface ICollection {
    // 索引签名, length需要和 index 返回值类型一致
	[index:number]:any;  // 通过数字类型 arr[0]访问
    [index2:string]:any;  // 可以通过字符串类型 obj['name']
    length:number
}

泛型

将类型当做参数传入

function foo<T>(arg:T):T{
  return arg
}

const res1 = foo<number>(123)

const res2 = foo<string>('aaa')

const res3 = foo<{name:string}>({name:'sss'})

// 省略写法
const res4 = foo('aaaaa')  // 会自动进行类型推理

接口泛型

interface IFoo<T = string> {
  name:T;
  age:number
}

const foo:IFoo<string> = {
  name:'xxx',
  age:22
}

const foo2:IFoo<number> = {
  name:222,
  age:22
}

// 默认类型 string
const foo3:IFoo = {
  name:'222',
  age:22
}

泛型类的使用

class Person<T = string> {
  name:T
  age:T
  constructor(name:T,age:T) {
    // ...
  }

}

const person  = new Person('123','123')

const person2  = new Person<number>(1,2)

泛型约束extends

不会丢失自身的类型属性

泛型参数约束

<O,T extends keyof O>

映射类型

只能使用type,不能使用interface

type MapPerson<T> = {
  [property in keyof T]:T[property]
}

interface Person{
  name:'sss0';
  age:33
}

type PersonCopy = MapPerson<Person>

可选属性

type MapPerson<T> = {
  [property in keyof T]?:T[property]
}

interface Person{
  name:'sss0';
  age:33
}

type PersonCopy = MapPerson<Person>

只读属性

type MapPerson<T> = {
  readonly [property in keyof T]?:T[property]
}

interface Person{
  name:'sss0';
  age:33
}

type PersonCopy = MapPerson<Person>

+和-

默认修饰符前是+,

-?: 去掉? 必传

type MapPerson<T> = {
  +readonly [property in keyof T]-?:T[property]
}

interface Person{
  name:'sss0';
  age:33
}

type PersonCopy = MapPerson<Person>

模块化

js 文件如果 有export 那么就被认为是一个模块

ts中 如果导入的类型,需要在类型前加 type 关键字

import type {IPerson} from './index.ts'

命名空间

目前使用ES module

namespace xxx {
  export function foo(){
    console.log(3)
  }
}

export {
  xxx
}

.d.ts文件

只写类型的声明,告知typescript 有哪些类型

  • 内置类型声明
    +
  • 外部定义类型声明
  • 自定义类型声明

declare 类型声明

// 声明变量,可以让在ts中使用这些变量而不报错
declare const name:string
declare const age:number

// 声明函数
declare function foo(bar:string): string

// 声明类
declare class Person {
  constructor(public name:string,public age:number)
}


// 声明文件模块
declare module "*.png"
declare module "*.svg"
declare module "*.jpg"
declare module "*.jpeg"

// 声明模块
declare module MyAxios {
  export const method:string
}

// 命名空间 $.axios
declare namespace $ {
	export function axios(config:any): any
}

tsconfig配置

创建:

tsc --init

使用:

tsc [filename]   // 如果跟文件,会忽略当前的tsconfig.js的配置

配置选项:

{
    "compilerOptions": {
      "target": "ESNext", // 将代码编译为最新版本的 JS
      "useDefineForClassFields": true, // 使用 Object.defineProperty 定义 class 中的属性,而非使用 obj.key = value 的形式定义属性
      "module": "ESNext", // 使用 ES Module 格式打包编译后的文件
      "moduleResolution": "Node", // 使用 Node 的模块解析策略
      "strict": true, // 启用所用严格的类型检查
      "jsx": "preserve", // 保留原始的 JSX 代码,不进行编译
      "sourceMap": true, // 生成 sourceMap 文件
      "resolveJsonModule": true, // 允许引入 JSON 文件
      "isolatedModules": true, // 该属性要求所有文件都是 ES Module 模块。
      "esModuleInterop": true, // 允许使用 import 引入使用 export = 导出的内容
      "lib": ["ESNext", "DOM"], // 引入 ES 最新特性和 DOM 接口的类型定义
      "skipLibCheck": true // 跳过对 .d.ts 文件的类型检查
    },
    files:[]  // 指定哪些ts文件需要编译,项目较小时适合
    include:[]  // 
	exclue:[],
	
}

条件类型

someType extends otherType ? TrueType: falseType  // 和 三元运算符类似

推断 infer

// 推断出类型,在true分支中返回
someType extends infer R ? R: never

分发类型

type toArray<T> = T extends any?T[]:never

type newType = toArray<number|string>  // 如果传入的是联合类型会进行分发 string[]|number[]
posted @ 2023-06-01 03:08  转角90  阅读(10)  评论(0编辑  收藏  举报