TS语法七 高级类型(二)

TS中的高级类型:
1.this类型
2.索引类型

  • 索引类型查询操作符
  • 索引访问操作符

3.映射类型

  • 基础
  • 由映射类型进行推断
  • 增加或移除特定修饰符

4.条件类型

  • 基础
  • 分布式条件类型
  • 条件类型的类型推断-infer
一 this类型

this也可以作为一种类型。

class Counter {
    constructor(public count: number = 0){}
    public add(value: number){
        this.count += value
        return this
    }
    public subtract(value: number){
        this.count -= value
        return this
    }
}

let count1 = new Counter(10)
console.log(count1.add(2).subtract(4))   //Counter {count: 8}

注意:通过this返回实例,从而实现了链式调用

二 索引类型

1.索引类型查询操作符keyof
连接一个类型,返回一个由这个类型的所有属性名组成的联合类型

interface Info {
    name: string
    age: number
}
let info1: keyof Info

info1 = 'name'
info1 = 'age'
// info1 = 'sex'  报错

function getValue<T, K extends keyof T>(obj: T, names: K[]): T[K][] {
    return names.map(n=>obj[n])
}
//这里的T[K][]也可以写成Array<T[K]>

const info2 = {
    name:'lyy',
    age:20
}
let value: (string|number)[] = getValue(info2, ['name', 'age'])
console.log(value) //['lyy', 20]

2.索引访问操作符[]

interface Info {
    name: string
    age: number
}

type nameType = Info['name']    //这里表示nameType为一个string类型
let name1:nameType = 'lyy---'
console.log(name1)   //lyy---

//返回属性值
function getProperty<T, K extends keyof T>(o: T, name: K): T[K] {
    return o[name]
}

//接口类型
interface Objs<T> {
    [key: string]:T
}

const objs:Objs<number> = {
    age: 18
}

let keys: keyof Objs<number> = objs['age']  //这里的keys类型为string|number
console.log(keys). //18

//注意,索引访问操作符不会返回null/undefined/never类型
interface Types {
    a: never
    b: string
    c: number
    d: undefined
    e: object
}

type Test = Types[keyof Type]  //type Test = string | number | object
三 映射类型

1.根据旧的类型创建出新的类型, 我们称之为映射类型。
看个例子:

interface Info {
    age: number
    name: string
    sex: string
}

如果给所有属性都加readonly,可以用下面的方法:

type ReadonlyType<T> = {
    readonly [p in keyof T]: T[p]   // 这里的in类似于js中的in,循环
}

type ReadonlyInfo = ReadonlyType<Info>
//type ReadonlyInfo = {
//     readonly name: string;
//     readonly age: number;
//     readonly sex: string;
// }

let info3:ReadonlyInfo = {
    age: 18,
    name: 'lyy',
    sex: 'male',
}
// info3.age = 20  报错,readonly不可修改

ts内置了很多类型, Readonly, Partial, Pick, Record等。
Readonly:添加只读
Partial:添加可选
Pick: 将原有类型中的部分内容映射到新类型中
Record:将一个类型的所有属性值都映射到另一个类型上并创造一个新的类型

type ReadonlyInfo2 = Readonly<Info>  //上面的例子可以直接用Readonly
type PartialInfo3 = Partial<Info> //属性置为可选
type testInfo = Partial<Readonly<Info>>;   //同时置为只读和可选

Pick例子:

type MyType = Pick<Info, 'name'>;
//type MyType = {
//    name: string;
// }

Record例子:

type Animal = 'person' | 'dog' | 'cat';

interface TestInterface {
    name: string;
    age: number;
}

type testType = Record<Animal, TestInterface>;

let res: testType = {
    person: {
        name: 'zs',
        age: 18
    },
    dog: {
        name: 'wc',
        age: 3
    },
    cat: {
        name: 'mm',
        age: 2
    }
}

console.log(res);

2.拆包
对于 Readonly,Partial 和 Pick 的映射类型, 我们可以对映射之后的类型进行拆包。
还原映射之前的类型, 这种操作我们称之为拆包。

interface TestInterface {
    name: string;
    age: number;
}

// 增加只读和可选属性
type TestType<T> = {
    +readonly [P in keyof T]+?: T[P];
}

type test = TestType<TestInterface>;
//type test = {
//    readonly name?: string;
//    readonly age?: number;
//}

// 删除只读和可选属性
type UnMyType<T> = {
    -readonly [P in keyof T]-?: T[P];
}

type test2 = UnMyType<test>;
四 条件类型

语法: T extends U ? X : Y;

1.简单的条件类型
type Type1<T> = T extends string ? string : number
let type1: Type1<false>  //let index: number
2.分布式条件类型
type Type2<T> = T extends any ? T : never
type type2 = Type2<string | number>  //type type2 = string | number

比较常用的是类型比较,比如从T中剔除U的类型:

type Diff<T, U> =  T extends U ? never : T
type type3 = Diff<string | number | boolean, undefined | number >  //type type3 = string | boolean
3.常用的几种类型

TS中已经封装了几种常用的类型:
(1)Exclude:从T中剔除U的类型
上例中可以这么写:

type type3 = Exclude<string | number | boolean, undefined | number >

(2)Extract:提取 T 中可以赋值给 U 的类型

type res = Extract<string | number | boolean, number | string> //type res = string | number

type res1 = Extract<string | boolean, number | string> //type res1 = string

(3)NonNullable: 从T中去掉null和undefined

type type9 = NonNullable<string | number | null | undefined>   //type type9 = string | number

(4)ReturnType:获取函数返回值类型

type type10 = ReturnType<()=> string>  //type type10 = string

(5)Parameters:获得函数的参数类型组成的元组类型

function say(name: string, age: number, gender: boolean) {
}

type res = Parameters<typeof say>;  //type res = [name: string, age: number, gender: boolean]
4.infer关键字

条件类型提供了一个 infer 关键字, 可以让我们在条件类型中定义新的类型
先来看个例子:
定义一个类型, 如果传入的是数组, 就返回数组的元素类型, 如果传入的是普通类型, 则直接返回这个类型。

type Type3<T> = T extends any[] ? T[number] : T
type type4 = Type3<string[]>   //type type4 = string       注意这里的T[number]
type type5 = Type3<string>  // type type5 = string      注意这里取的是T

如果用infer实现:

type Type4<T> = T extends Array<infer U> ? U : T
type type6 = Type4<string[]>

在条件类型表达式中,可以在 extends 条件语句中使用 infer 关键字来声明一个待推断的类型变量。
infer的作用是让TypeScript自己推断,并将推断的结果存储到一个类型变量中,infer只能用于extends语句中。

// 如果泛型T是()=> infer R的子集,则返回infer R获取到的类型,否则返回boolean
type Func<T> = T extends () => infer R ? R : boolean;

let func1: Func<number>; // boolean;
let func2: Func<''>; // boolean
let func3: Func<() => Promise<number>>; // Promise<number>

再看个例子:

type Obj<T> = T extends { a: infer VT, b: infer VT } ? VT : number;

let obj1: Obj<string>;  // number;
let obj2: Obj<true>;  // number;
let obj3: Obj<{a: string, b: string}>;   // string
let obj4: Obj<a: number, b: string>;   // string | number
// 当a、b为不同类型时,返回联合类型
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: JavaScript(JS)是一种脚本语言,用于Web开发中的动态交互和客户端脚本编程。TypeScript(TS)是一种由Microsoft开发的编程语言,它是JavaScript的超集,增加了静态类型检查和其他特性。 主要区别如下: - 类型系统:TS具有静态类型检查,而JS没有。 - 扩展性:TS允许定义接口,枚举,抽象类等高级结构,使得代码更易于维护和扩展。 - 兼容性:TS可以与JS代码相互兼容,但是JS不能直接运行TS代码。 将JS转换为TS可以通过以下方式: - 重写代码:手动将JS代码重写为TS代码,并添加必要的类型注释和其他特性。 - 使用工具:可以使用一些工具,例如JS to TS Converter,将JS代码自动转换为TS代码,但是需要手动进行一些修正和调整以满足TS的要求。 - 引入.d.ts文件:如果JS文件已经有对应的.d.ts文件(即类型声明文件),则可以直接引入该文件,以便在TS中使用。 ### 回答2: JS(JavaScript)和TS(TypeScript)是两种不同的编程语言,它们之间存在以下区别: 1. 静态类型 vs 动态类型:JS是一种动态类型的语言,变量可以在运行时改变其类型;而TS是一种静态类型的语言,变量必须在编译时声明并且不能改变其类型。 2. 类型注解和类型推断:TS允许开发者在变量声明时使用类型注解,明确指定变量的类型,提供了更好的代码可读性和可维护性;而JS不支持类型注解,类型是通过运行时推断得出的。 3. 类型检查:TS具有编译时的类型检查,它可以检测出潜在的类型错误,减少运行时错误的发生;而JS只有在运行时才能发现类型错误。 4. ECMAScript标准的支持:TS是基于最新的ECMAScript标准的超集,它包含了ECMAScript的全部特性,并且可以使用ES6+的新语法;而JS的语法受限于特定的ECMAScript版本。 将JS转换为TS可以通过以下步骤进行: 1. 将JS文件的后缀名改为.ts,表示它是一个TS文件。 2. 分析原始代码,添加类型注解。根据需要,对变量、函数和方法等添加适当的类型注解,以使其具备静态类型。 3. 修复类型错误。使用TS编译器(tsc)编译时,它会给出类型错误的提示,根据提示进行相应的修复,确保代码通过类型检查。 4. 编译TS文件为JS文件。使用tsc命令将.ts文件编译为.js文件,生成可以在浏览器中运行的JS代码。 总结起来,JS和TS的主要区别在于类型系统的支持和类型检查。要将JS转换为TS,需要为代码添加类型注解,并对类型错误进行修复,最后将TS文件编译为JS文件。这样可以提高代码的可读性、可维护性,并减少潜在的类型错误。 ### 回答3: JS和TS是两种不同的编程语言。JS是一种动态类型的脚本语言,广泛应用于Web开发中。而TS是JS的超集,也是一种编程语言,它在JS的基础上增加了静态类型、面向对象等特性。 首先,JS和TS的区别在于类型系统。JS是一种动态类型语言,变量的类型可以在运行时动态改变。而TS是静态类型语言,变量在定义时必须指定其类型,并且不能改变。静态类型可以帮助开发者在编码过程中发现潜在的类型错误,提高代码的可靠性和可维护性。 其次,TS具备了更强大的面向对象特性。它支持类、接口、继承、泛型等高级语法特性,可以更好地组织和管理复杂的代码结构。 要将JS转换为TS,可以遵循以下步骤: 1. 修改文件的后缀名为.ts,表示该文件为TS代码。 2. 根据需要,在变量声明时添加类型注解。例如,将 'let x = 10;' 改为 'let x: number = 10;',指定变量 x 的类型为 number。 3. 添加类型定义文件(.d.ts)或使用现有的类型定义文件。类型定义文件用于描述库、框架或第三方模块的类型信息,以便在TS中正确地使用它们。 4. 检查代码中的类型错误。由于TS是静态类型语言,编译器可以检测出潜在的类型错误,并给出相应的警告或错误提示。根据编译器的提示,修复代码中的类型错误。 5. 通过使用编译器选项或构建工具(如webpack)将TS代码编译为JS代码。编译器会将TS代码转换为与JS兼容的代码,以便在浏览器或Node.js环境中运行。 总的来说,将JS转换为TS需要添加类型注解、修复类型错误并进行编译。这样可以在保留原有JS代码的同时,享受到TS静态类型检查和更强大的面向对象特性带来的好处。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值