typescript学习

TS有什么优缺点,为什么要用TS

优点:
1.可以减少低级语法错误
2.规范团队代码,对大型项目来说,规范很重要
3.定义类型,可以让编辑器更好的自动提示,提升代码效率
缺点:
1.学习成本高
2.开发成本高,又要开发业务,又要编写类型文件,有时候还需要解决奇奇怪怪的类型报错
适用场景:
1.大型项目和团队开发
2.库和框架开发
3.对于一些重要的逻辑或者代码,可以使用ts来增强其可靠性

typescript 的数据类型有哪些

基本类型:number、string、boolean、null、undefined、symbol、bigint
数组类型:number[]、string[]、boolean[]、Array、Array、Array
元组类型:[number, string, boolean]
枚举类型:enum Color {Red, Green, Blue}
Any类型:any
Void类型:void
Object类型:object、Object
Never类型:never

TypeScript 中枚举类型的理解

枚举类型是 TypeScript 中的一种数据类型,它允许我们定义一些具名的常量集合。使用枚举类型可以更加直观地表达代码含义,提高代码可读性和可维护性。
在 TypeScript 中,枚举类型通过enum关键字进行定义。例如:

enum Direction {
	Up,Down,Left,Right
}

在这个例子中,我们定义了一个名为 Direction 的枚举类型,其中包含了四个常量成员:Up、Down、Left 和 Right。默认情况下,枚举成员的值会从0开始自动编号,也可以手动指定值

TypeScript 中接口的理解

在 TypeScript 中,接口(Interface)是一种抽象的定义,用来描述对象的形状。它定义了一个对象应该具有的属性和方法。

接口的应用场景很广泛,例如在定义函数参数时,可以使用接口来规范参数的类型和结构;在定义类时,可以使用接口来规范类的结构;在定义复杂的对象类型时,可以使用接口来提高代码的可读性和可维护性。

// 先定义一个接口
interface IUser {name: string;age: number;
}
const getUserInfo = (user: IUser): string => {return `name: ${user.name}, age: ${user.age}`;
};
// 正确的调用
getUserInfo({name: "koala", age: 18});

TypeScript 中类的理解

在 TypeScript 中,类是一种定义对象属性和方法的结构化方式,使用 class 关键字来定义。

类可以包含属性和方法,通过实例化类可以创建对象,对象可以访问类中定义的属性和方法。

与 JavaScript 不同的是,TypeScript 中的类可以使用访问修饰符来控制属性和方法的访问级别,如 public(默认值,可以自由的访问类程序里定义的成员)、private(只能够在该类的内部进行访问) 和 protected(除了在该类的内部可以访问,还可以在子类中仍然可以访问)。

类也可以继承其他类,使用 extends 关键字来实现继承,从而可以复用已有的类定义。

类还可以实现接口,这种方式称为类实现接口,使用 implements 关键字来实现接口。

总的来说,类是面向对象编程的基本组成部分,可以通过类来创建具有一定属性和行为的对象,并且 TypeScript 中的类支持访问修饰符和继承等面向对象编程的概念,使得代码更加规范和易于维护

什么是泛型,有什么作用?

TS泛型简单来说就是类型参数,在定义某些函数、接口和类时,不写死类型,而是改用类型参数的形式,让类型更加灵活。

举个简单的例子,我们定义一个数据响应体的接口:

interface IResponseData<T>{
    code: number;
    message?: string;
    data: T;
}

其中data的类型并没有写死,而是可以在我们使用的时候传入:

interface User {
  id: number;
  name: string;
  email: string;
}

// 使用时传入User类型
const response: IResponseData<User> = {
  code: 200,
  message: "Success",
  data: {
    id: 1,
    name: "xiaoming",
    email: "xxx@qq.com"
  }
};

1.泛型函数:使用泛型来定义函数的参数和返回值类型。

function identity<T>(arg: T): T {return arg;
}

定义泛型的时候,可以一次定义多个类型参数,比如我们可以同时定义泛型 T 和 泛型 U:

2.泛型接口:使用泛型来定义接口的属性或方法。

interface Array<T> {
	length: number;
	push(...items: T[]): void;
	forEach(callbackfn: (value: T, index: number, array: T[]) => void): void;
}

3.泛型类:使用泛型来定义类的属性和方法的类型。

class GenericNumber<T> {
	zeroValue: T;add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

TypeScript 中高级类型的理解?

1.交叉类型
使用&符号表示,可以将多个类型合并成一个类型。

2.联合类型
使用|符号表示,可以表示一个值属于多种类型之一。

3.类型别名
使用 type 关键字定义一个类型别名,方便在其他地方引用该类型。

4.类型索引
keyof 类似于 Object.keys ,用于获取一个接口中 Key 的联合类型。

interface Button {type: stringtext: string}type ButtonKeys = keyof Button// 等效于type ButtonKeys = "type" | "text"

5.类型约束
6.映射类型
通过 in 关键字做类型的映射,遍历已有接口的key或者是遍历联合类型

type Readonly<T> = {readonly [P in keyof T]: T[P];
};interface Obj {a: stringb: string
}type ReadOnlyObj = Readonly<Obj>

上述的结构,可以分成这些步骤:

keyof T:通过类型索引 keyof 的得到联合类型 ‘a’ | ‘b’
P in keyof T 等同于 p in ‘a’ | ‘b’,相当于执行了一次 forEach 的逻辑,遍历 ‘a’ | ‘b’
所以最终ReadOnlyObj的接口为下述:

interface ReadOnlyObj {readonly a: string;readonly b: string;
}

7.条件类型
使用extends关键字和三目运算符 ? 和 :,可以根据类型关系推断出另一个类型

类型别名type和接口interface有什么区别?

1.类型别名不能被继承或者实现,接口可以被继承或者实现。
2.类型别名可以定义任何类型,包括联合类型、交叉类型、字面量类型、原始类型等。接口只能定义对象类型,包括属性、方法、索引等。
3.类型别名通常用于为复杂类型创建别名,以方便在代码中使用。接口通常用于定义某个实体的结构,以及实现该结构的对象或类。
总结一下,如果你需要定义一个对象类型,或者需要使用继承和实现的特性,那么应该使用接口;如果你需要定义任意类型的别名,或者需要定义联合类型和交叉类型等复杂类型,那么应该使用类型别名。

什么是装饰器?

装饰器的作用,简单来说就是代码复用,和Java里的注解以及Rust里的属性宏类似。

把通用的代码封装成装饰器,然后在使用的时候就可以将@xxx添加在方法或者类上,方法和类就得到了加强,特别简洁优雅。

例如mobx里的@observable以及NestJS里的@Controller。

举个简单的自定义装饰器例子,我们来实现一个自动打印函数参数以及返回值的装饰器。

首先来定义装饰器:

// target表示装饰的目标对象
// propertyKey表示装饰的属性或方法名
// descriptor表示属性或方法的描述符
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  
  descriptor.value = function (...args: any[]) {
    console.log(`调用 ${propertyKey},参数为: ${JSON.stringify(args)}`);
    const result = originalMethod.apply(this, args);
    console.log(`方法 ${propertyKey} 返回值为: ${JSON.stringify(result)}`);
    return result;
  };
  
  return descriptor;
}

然后使用一下这个装饰器

class Test {
  @log
  add(a: number, b: number) {
    return a + b;
  }
}

const test = new Test();
console.log(test.add(2, 3)); // 会打印出参数2,3和返回值5

any用的多吗,有什么弊端?

使用any类型的主要目的是在不清楚变量类型的情况下避免编译错误,但是,频繁地使用any类型那就等于白白浪费了TS的类型检查能力。

正确的做法是尽可能避免使用any类型,尽可能地使用明确的类型,这样可以提高代码的可读性和可维护性,并且可以减少潜在的运行时错误。

但是有时候时间紧任务重又不得不用,所以一句话总结就是,尽量不用,不到万不得已不轻易用any。

你知道哪些工具类型,怎么用?

工具类型主要用于处理和转换已有类型,它们不是实际的类型,而是用来处理类型的工具。

工具类型可以认为是TS类型的工具函数,把原有类型当参数来处理。

举一个工具类型Partial应用的例子:

// 已有类型User
interface User {
  name: string;
  age: number;
}

// 新类型PartialUser,使用Partial将属性都变成可选
type PartialUser = Partial<User>; // { name?: string; age?: number; }

常用工具类型有:

Partial:将类型 T 的所有属性变为可选属性。
Required:将类型 T 的所有属性变为必选属性。
Readonly:将类型 T 的所有属性变为只读属性。
Record<K, T>:创建一个类型,其中属性名为类型 K 中的值,属性值为类型 T 中的值。
Pick<T, K>:从类型 T 中选择属性名为类型 K 中的属性,创建一个新类型。
Omit<T, K>:从类型 T 中排除属性名为类型 K 中的属性,创建一个新类型。
Exclude<T, U>:从类型 T 中排除类型 U 中的所有属性。
Extract<T, U>:从类型 T 中提取类型 U 中存在的所有属性。
NonNullable:从类型 T 中移除 null 和 undefined。
ReturnType:获取函数类型 T 的返回值类型。

TS里怎么处理第三方库类型,怎么给第三方库编写类型文件?

TS社区维护了一个名为DefinitelyTyped的项目,提供了大量的第三方库的类型定义文件,大多数三方库类型文件都可以直接在这里面下载。

但是如果第三方库没有提供类型定义文件时,我们可以通过手动编写类型文件的方式,为第三方库添加类型支持。

给三方库编写类型的文件步骤如下:

创建d.ts文件:在项目中创建一个新的d.ts文件,文件名可以与库名相同,例如lodash.d.ts。
定义模块:使用declare module语句定义模块名,模块名应与库的导出模块名一致。例如,对于lodash库,可以这样定义模块:

declare module 'lodash' {
  // 在此处添加类型定义
}

添加类型定义:在模块内部添加对应的类型定义,例如函数、变量、类等。根据需要,可以使用 interface、type、class 等关键字定义不同类型的接口。
导出类型:使用 export 关键字导出需要公开的类型。例如,对于以下的 utils 函数,可以这样定义:

declare module 'lodash' {
  function utils(...args: any[]): any;
  export { utils };
}

使用类型文件:在需要使用第三方库的地方,通过import语句引入类型定义即可:

import { utils } from 'lodash';

Vue项目怎么使用TS?

Vue2项目可以通过添加 class-component 和 vue-property-decorator 库来使用TS。
Vue3对TS支持更好,可以通过vue-cli或者vite来直接启动TS模板的脚手架。

实战

新创建一个项目
第一步,终端安装typescript

lvzhichao@lvzhichaos-iMac lzc-ts % npm i -g typescript

终端运行下tsc命令

lvzhichao@lvzhichaos-iMac lzc-ts % tsc index.ts
zsh: command not found: tsc

嗯???
我的是mac,为啥要用npm安装。。。
重新安装下

brew install typescript

安装成功
在这里插入图片描述
执行tsc命令
在这里插入图片描述

每次改完ts文件代码,都需要重新跑一下tsc命令,这是不能容忍的,那么久需要用到这个命令

tsc index.ts -w

请添加图片描述
自动监听文件,当代码变化,自动编译

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值