Typescript学习总结和知识分享
介绍
最近学习使用了 Typescript
的一些语法,总结成本文,分享给大家。
由于JavaScript
是弱类型语言,在项目代码里越来越大时,特别是一个多人维护的项目中,其弱类型的特点,使得我们往往不直观清楚其他人写的函数是什么意思、需要传入什么参数、返回值是什么。
JavaScript
往往需要维护大量的代码注释或者接口文档来供其他人了解,导致大项目很难维护,但是使用TypeScript
后,除了初期一些学习成本外,则可以很好的解决上面的问题。
TypeScript
是JavaScript
的严格超集。Vue3.x
也已经全部使用TypeScript
开发。
TypeScript的内置数据类型
Boolean 类型
const flag: boolean = true;
Number 类型
const age: number = 6;
String 类型
const name: string = '海康'
Enum 类型
enum Color {
BLUE,
BLACK,
GOLD,
PINK
}
const pink: Color = Color.PINK;
console.log(pink); // 3
Array 类型
const array1: string[] = ['海康', '大华', '华为']
const array2: Arrary<string> = ['海康', '大华', '华为']
元祖tupple 类型
对于内部不同类型的数组可以使用元组类型来定义。
const array3: [number, string] = [1, '海康']
对象类型
// 方式一
let bObj: Object = null;
bObj = 1;
bObj = 'b';
bObj = true;
bObj = {
b: '1'
}
// 方式二
let aObj: {} = null;
aObj = 1;
aObj = 'a';
aObj = true;
aObj = {
a: '2'
}
undefined
默认情况下undefined 是所有类型的子类型
let a: string = undefined;
null
默认情况下 null 是所有类型的子类型
let a: string = null;
any
any会跳过类型检查器对值的检查
let num: any = 1;
void
一般用在函数上,表示函数没有返回值
function showDialog(): void {
console.log('dialog')
}
never
表示的是那些永不存在的值的类型
// 异常
function error(msg: string): never {
throw new Error(msg);
}
unknown
unknown 任何类型的值都可以赋值给它,但它只能赋值给unknown和any
let str: unknown = '海康';
str = 1;
str = true;
TypeScript中自定义的数据类型
类
class Animal {
name: '动物',
age: 1,
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
run(): void {
console.log('run')
}
}
函数
// 方式一:函数声明
function add(a: number, b: number): number {
return a + b;
}
// 方式二:函数表达式
const add = function(a: number, b: number): number {
return a + b;
}
// 方式三: 可选参数
function add(a: number, b?: number): number {
return b ? a + b : a;
}
// 方式四:参数默认值
function add(a: number, b: number = 0): number {
return a + b;
}
// 方式五:剩余参数
function add(...params: number[]): number {
let sum = 0;
const len = params.length;
for(let i=0; i<len; i++) {
sum += i;
}
return sum;
}
接口
使用接口来定义对象的类型
// 方式一
interface Animal {
name: string;
age: number;
run: void;
}
// 方式二
interface Animal {
name: string;
age?: number;
run: void;
}
// 方式三
interface Animal {
name: string;
age?: number;
[prop: string]: any;
}
const a1 = { name: 'dog' }
const a2 = { name: 'cat', age: 1 }
const a3 = { name: 'pig', card: 'pig01' }
// 方式四
interface Animal1 {
name: string;
run(): void;
}
interface Animal2 extends Ainmal1 {
sex: string
}
let dog: Animal2 = {
name: 'dog1',
sex: '1',
run(): void {
console.log('running')
}
}
类型断言
某些情况下,我们可能比typescript
更加清楚的知道某个变量的类型,可能希望手动指定一个值的类型
let name: any = '海康';
// 需要断言为string类型时
let nameLen: number = (<string>name).length;
// 或者
let nameLen2: number = (name as string).length;
类型推断
变量声明时,如果有赋值,那么 TypeScript
会依照类型推论规则,推断出一个类型。如果没有赋值,会被推断为 any
类型。
let x = 1;
// 会被推断为
let x: number = 1;
let y;
// 会被推断为
let y: any;
联合类型
变量具有多个类型,多个类型是 或 的关系;
let status: number | string = 1;
status = '2';
交叉类型
变量具有多个类型,多个类型是 与 的关系;
interface typeName {
name: string
}
interface typeAge {
age: number
}
let company: typeName & typeAge {
name: '海康',
age: 22
}
类型别名
用来给一个类型起个新名字
type count = number;
let age: count = 1;
类型守卫
运行时检查,确保一个值在所要类型的范围内
// in
interface InObj {
a: number,
b: string
}
function isIn(arg: InObj) {
if ('x' in arg) {
console.log('x在InObj内')
}
}
// typeof
function isType(val: string | number) {
if (typeof val === 'number') {
return 'number'
}
if (typeof val === 'string') {
return 'string'
}
return ''
}
// instanceof
function isDate(date: Date | string) {
if (date instanceof Date) {
return date.getDate()
} else {
return new Date(date)
}
}
高级用法
泛型
泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
// 方式一:一个参数
function getValue<T>(arg: T): T {
return arg;
}
// 使用
getValue<string>('海康');
// 或者
getValue('海康');
// 方式二:多个参数
function getValue<T, U>(arg: [T, U]): [T, U] {
return arg;
}
// 使用
getValue<string, number>(arg: [string, number]): [string, number];
// 或者
getValue(['海康', 2])
泛型约束
可以使用extends
关键字来对泛型进行约束。
interface LengthType {
length: number;
}
function getLength<T extends LengthType>(arg: T): T {
return arg.length;
}
// 使用
const str = getLength('海康');
const arr = getLength([1, 2, 3]);
const obj = getLength({ length: 5 });
泛型接口
interface KeyValue<T, U> {
key: T,
vlaue: U
}
const animal1: keyValue<string, number> = {
key: 'dog',
value: 10
}
泛型类
class Type<T> {
value: T;
add: (x: T, y: T) => T;
}
let add = new Type<number>();
add.value = 0;
add.add = function(x, y) {
return x + y;
}
泛型类型别名
type Dog<T> = { list: T[] } | T[];
let d1: Dog<number> = [1];
let d2: Dog<string> = { list: ['2'] };
泛型工具类型
typeof 从实现推出类型
let obj1 = {
name: '海康',
age: 22
}
type Company1 = typeof obj1;
function getCompany(c: Company1): string {
retrun c.name;
}
keyof 接口对象中的所有key值
interface Company {
name: string,
age: number
}
type CompanyKey = keyof Company;
// type CompanyKey = 'name' 、'age'
in 遍历枚举类型
type Keys = 'a' | 'b' | 'c';
type K1 = {
[k in Keys]: any
}
// type K1 = { a: any, b: any, c: any }
infer 声明一个类型变量
extends 添加泛型约束
interface LengthType {
length: number;
}
function getLength<T extends LengthType>(arg: T): T {
return arg.length;
}
// 使用
const str = getLength('海康');
const arr = getLength([1, 2, 3]);
const obj = getLength({ length: 5 });
[] 进行索引访问
interface Company {
name: string;
age: number;
}
type x = Company["name"];
// x is string
内置工具类型
Required 接口的属性转为必选
interface Company {
name?: string,
age?: number
}
const comp: Required<Company> = {
name: "海康威视",
age: 18
}
Partial 接口的属性转为可选
interface Company {
name: string,
age: number
}
const comp: Required<Company> = {
name: "海康威视"
}
Exclude 将某个类型中属于另一个的类型移除掉,剩余的属性构成新的类型
type T0 = Exclude<"a" | "b" | "c", "a">;
// "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">;
// "c"
type T2 = Exclude<string | number | (() => void), Function>;
// string | number
Extract 取交集类型
type T0 = Extract<"a" | "b" | "c", "a" | "f">;
// "a"
type T1 = Extract<string | number | (() => void), Function>;
// () => void
Readonly 变为只读,使之不可重新赋值
interface Company {
name: string,
age: number
}
let p: Readonly<Company> = {
name: "hello",
age: 10
};
// 使用
p.age = 11;
// error Cannot assign to 'age' because it is a read-only property.
Record
type Property = 'key1' | 'key2'
type Company = Record<Property, string>;
const p: Company = {
key1: "海康",
key2: "大华",
}
Pick 从某个类型中挑出一些属性出来
type Company = {
name: string;
age:number;
instructor:string
}
type P1 = Pick<Company, "name" | "age">;
// { name: string; age: number; }
const user:P1 = {
name: '海康',
age: 22
}
Omit<T, K> 从T中取出除去K的其他所有属性
interface Person {
name: string,
age: number,
industry: string
}
type P1 = Omit<Person, "age" | "industry">
const user:P1 = {
name: '海康'
}
NonNullable 去除类型中的 null 和 undefined
type P1 = NonNullable<string | number | undefined>;
// string | number
type P2 = NonNullable<string[] | null | undefined>;
// string[]
ReturnType 用来得到一个函数的返回值类型
type Func = (value: string) => string;
const test: ReturnType<Func> = "1";
Parameters 用来得到一个函数的参数类型
type P1 = Parameters<(a: number, b: string) => void>;
// [number, string]
InstanceType 返回构造函数类型T的实例类型
class C {
x = 0;
y = 0;
}
type D = InstanceType<typeof C>;
// C