06 ts扩展知识

 

目录

ts模块化

命名空间

类型声明

tsconfig.json文件

条件类型(了解)

条件类型-类型推断infer

分发条件类型

内置工具-类型体操

Partial

Required

Readonly

Record

pick

omit

其他


ts模块化

 ts从2012年开始跟进模块化,ts支持多种模块化方案

2015年esmodule发布,所以在ts中最主要使用的模块化方案就是es module

用法与在js中使用无异,这里说明一些特殊用法

 内置类型导入

// 导入其他函数与js的esmodule一样
import {sum} from './utils/Math'
// 在导入类型时,最好加上type
import {type IPerson,type IKun} from './utils/type'
// 加上type优点: 在babel等进行打包编译时可以去掉
// 其他写法: 当导入的全是type时,type可以写在外边
// import type {IPerson, IKun} from './utils/type'
console.log(sum(10,20));
const obj: IPerson = {
    name: 'zhao',
    age: 12
}

命名空间

ts在ES module前推出的模块化方案,现已经不推荐使用

// 命名空间,不同命名空间变量名可重复
namespace price {
    function format() {}
    const name = 'xx'
}
// 导出
export namespace data {
    // 这个也需要导出
    export function format() {}
    // 没导出只能自己内部使用
    const name = 'zz'
}

类型声明

在我们开发中所用的类型,有些是我们自己写的,但也用到了一些别的内容(HTMLDivElement)

这些类型来自哪里?这与ts类型的管理与查找规则有关

.d.ts文件

类型声明文件 .d.ts文件 用来做类型声明, 不能在里面写逻辑代码,

仅仅用来做类型检测,告诉ts我们有哪些类型

类型分明大致分为三种:

    1,内置类型声明(HTMLImageElement,Promise等)

    2,外部定义类型声明(我们引入的第三方库,例如axios)

    3,自己定义类型声明

tsconfig.json文件

作用一:  让TypeScript Compiler在编译时,知道如何去编译ts和进行类型检测

    比如: 将ts代码编译成什么版本的javascript代码,

作用二:  让编译器(vscode)可以按照正确的方式识别ts代码

    比如:  对那些语法进行提示,类型错误检测等等

tsconfig.json在编译时如何被使用?

在调用tsc时,指定文件,tsc index.ts 会将改文件编译成js文件

只使用tsc命令,找到包含tsconfig.json目录(根目录)编译所有ts文件

在webpack中使用ts-loader进行打包时,会自动读取tsconfig文件,根据配置编译ts代码

tsconfig.json常用选项

当我们在开发中,选择ts模板时,会自动配好,一般不需要我们修改

条件类型(了解)

type myType = number | string

// 语法: type1 extends type2 ? trueType : falseType
// 类似于js中的三元运算符 如果type1继承type2则返回trueType,否则返回falseType
// 只有extends这一种判断

//应用

// function sum(num1: number,num2: number): number
// function sum(num1: string,num2: string): string
function sum<T extends myType>(num1: T,num2: T): T extends number ? number : string
function sum(num1: any, num2: any) {
    console.log(num1+num2);
    return num1+num2
}
sum('str','xxx')
sum(1,2)

export {}

条件类型-类型推断infer

// 条件类型提供了infer关键词,可以从正在比较的类型中推断类型,然后再true分支中引用

// 应用: 假如我们现在有一个函数类型,获取他的参数类型与返回值类型
// ts有内置工具ReturnType
type fnType = ()=>void
type fnType2 = (num1: number,num2: number)=>number
type fnType3 = (num1: string,num2: string)=>string

type resType = ReturnType<fnType>
// 获取返回值类型
type myReturnType<T extends (...args: any[])=>any> = T extends (...args: any[])=> infer R ? R : never
// 获取参数类型
type myParamsType<T extends (...args: any[])=>any> = T extends (...args: infer P)=> any ? P : never

// 测试
type resType2 = myReturnType<fnType2>
type resType3 = myReturnType<fnType3>

type resType4 = myParamsType<fnType2>
type resType5 = myParamsType<fnType3>

分发条件类型

// 当我们在泛型中使用条件类型,如果传入一个联合类型,就会变成分发的

// 应用: toArray
type toArray<T> = T[]

type numArr = toArray<number>
type numStrArr = toArray<number | string> // (number | string)[] 想要的是 number[] | string[]
// 分发条件类型
type toArray2<T> = T extends any ? T[] : never
type numStrArr2 = toArray2<number | string> //  number[] | string[]

内置工具-类型体操

Partial

// 将一个对象类型的所有参数变成可选的
interface IKun {
    name: string,
    age: number,
    slogan: string
}

type newIKun = Partial<IKun>
// 实现
type MyPartial<T> = {
  [P in keyof T]?: T[P]
}
type newIKun2 = MyPartial<IKun>

Required

// 将一个对象类型的所有参数变成必选的
interface IKun {
    name: string,
    age: number,
    slogan?: string
}

type newIKun = Required<IKun>
// 实现
type MyRequired<T> = {
  [P in keyof T]-?: T[P]
}
type newIKun2 = MyRequired<IKun>
export {}

Readonly

// 将一个对象类型的所有参数变成必选的
interface IKun {
    name: string,
    age: number,
    slogan?: string
}

type newIKun = Readonly<IKun>
// 实现
type MyReadonly<T> = {
  readonly [P in keyof T]: T[P]
}
type newIKun2 = MyReadonly<IKun>
export {}

Record

// record: 接受两个参数,返回一个对象类型
//第一个参数是一个联合类型,每一项作为key
// 第二个参数作为value
interface IKun {
    name: string,
    age: number,
    slogan?: string
}
type keys = '上海' | '北京'
type newIKun = Record<keys,IKun>
const IKun1: newIKun = {
    '上海' : {
        name: 'xxx',
        age: 10
    },
    '北京' :{
        name: 'yyy',
        age: 5
    }
}
// 实现
// K必须是联合类型,keyof any返回 number | string | symbol
type MyRecord<K extends keyof any,T> = {
    [P in K]: T
}
type newIKun2 = MyRecord<keys,IKun>
export {}

pick

// pick: 接受两个参数,
// 第一个参赛: 一个对象类型
// 第二个参数: 第一个参数key的联合类型的子集
// 返回: 一个对象类型,所有的key是第二个参数选项

interface IKun {
    name: string,
    age: number,
    slogan?: string
}

type newIKun = Pick<IKun,'name'| 'slogan'>
// 结果
// type newIKun = {
//     name: string;
//     slogan?: string | undefined;
// }
// 实现

type MyPick<T,K extends keyof T> = {
    [P in K]: T[P]
}
type newIKun2 = MyPick<IKun,'name'| 'slogan'>
export {}

omit

// omit: 作用与pick相反 接受两个参数,
// 第一个参赛: 一个对象类型
// 第二个参数: 第一个参数key的联合类型的子集
// 返回: 一个对象类型,去除第二个参数的key

interface IKun {
    name: string,
    age: number,
    slogan?: string
}

type newIKun = Omit<IKun,'name'| 'slogan'>
// 结果
// type newIKun = {
//     age: number;
// }
// 实现

type MyOmit<T,K extends keyof T> = {
    // 获取所有key,看key在不在K中,做一次判断
    [P in keyof T as P extends K ? never : P]: T[P]
}
type newIKun2 = MyOmit<IKun,'name'| 'slogan'>
export {}

其他

exclude<联合类型,去除的项>

extract<联合类型,只包含的项>

NonNullable<联合类型> : 去除联合类型中的null与undefined

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 可以,泛型继承是指在定义泛型类时,可以通过继承其他泛型类或接口来扩展泛型类型的能力。在 TypeScript 中,可以使用 extends 关键字来实现泛型继承。例如,可以定义一个泛型类 A,然后定义一个泛型类 B,让 B 继承 A,这样 B 就可以使用 A 中定义的泛型类型参数和方法。 ### 回答2: 在TypeScript中,泛型继承通常用于扩展和重用代码。它允许我们建立一个父级泛型类或接口,并从中继承并扩展子级泛型类或接口。 首先,我们可以使用泛型参数来定义父级类或接口。这个泛型参数可以在类的方法或接口的成员中使用,以代表一个类型参数。 例如,我们可以定义一个泛型类`Box<T>`,表示一个具有特定类型的盒子。然后,我们可以通过使用泛型继承来扩展这个`Box<T>`类,从而创建一个更具体的子类,例如`NumberBox<T>`,表示一个具有特定类型的数字盒子。 像这样: ```typescript class Box<T> { item: T; constructor(item: T) { this.item = item; } getItem(): T { return this.item; } } class NumberBox<T extends number> extends Box<T> { getSum(): number { let sum = 0; for(let i = 0; i <= this.item; i++) { sum += i; } return sum; } } const numberBox = new NumberBox(5); console.log(numberBox.getItem()); // 输出: 5 console.log(numberBox.getSum()); // 输出: 15 ``` 在上面的例子中,我们定义了一个`Box<T>`类,它有一个泛型参数`T`和一个`getItem`方法用于获取盒子中的物品。然后,我们通过使用`extends`关键字来扩展`Box<T>`类,从而创建了一个`NumberBox<T>`子类。这个`NumberBox<T>`子类添加了一个`getSum`方法,用于计算数字盒子中所有数字的总和。在实例化`NumberBox`时,我们可以传入一个数字类型的参数。 通过泛型继承,我们可以在子级类中访问和使用父级类中定义的属性和方法,并在子级类中添加更专用的功能来满足特定的需求。这样,我们可以更好地扩展和重用代码,使其更灵活和可维护。 ### 回答3: 在 TypeScript 中,泛型继承可以用于让一个泛型类或接口继承另一个泛型类或接口,从而扩展其功能或限制其使用。通过使用泛型继承,我们可以在类型层面上实现一种继承关系,使得一个泛型类或接口可以继承另一个泛型类或接口的特性。 泛型继承可以通过使用`extends`关键字来实现。当一个泛型类或接口要继承另一个泛型类或接口时,可以在泛型参数后面使用`extends`关键字指定要继承的类型。通过这种方式,子类或衍生类可以继承父类或基类的泛型参数,以及其他定义在父类或基类中的属性和方法。 使用泛型继承可以提供类型的灵活性和重用性,使得代码更加可维护和可扩展。通过定义一个泛型基类或接口,不仅可以使用现有的泛型规则和逻辑,还可以添加新的泛型参数和属性来适应不同的需求。同时,子类或衍生类可以继承并扩展基类或父类的特性,从而实现更多的功能拓展和共享。 值得注意的是,泛型继承可以帮助我们避免代码的冗余和重复,提高代码的可重用性和可维护性。通过合理运用泛型继承的机制,我们可以更好地抽象和封装代码,减少重复的代码片段,提高代码的可读性和可扩展性。 总之,通过使用泛型继承,我们可以在 TypeScript 中实现通过继承来扩展和重用泛型类或接口的功能。这种机制使得类型的定义更加灵活和可扩展,同时还能提升代码的可维护性和可重用性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值