Typescript知识点总结分享

163 阅读6分钟

Typescript学习总结和知识分享

介绍

最近学习使用了 Typescript 的一些语法,总结成本文,分享给大家。

由于JavaScript是弱类型语言,在项目代码里越来越大时,特别是一个多人维护的项目中,其弱类型的特点,使得我们往往不直观清楚其他人写的函数是什么意思、需要传入什么参数、返回值是什么。

JavaScript往往需要维护大量的代码注释或者接口文档来供其他人了解,导致大项目很难维护,但是使用TypeScript后,除了初期一些学习成本外,则可以很好的解决上面的问题。

TypeScriptJavaScript的严格超集。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 {
  namestring;
  agenumber;
}

type x = Company["name"];
// x is string
内置工具类型

Required 接口的属性转为必选

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

const compRequired<Company> = {
    name"海康威视",
    age18
}

Partial 接口的属性转为可选

interface Company {
    namestring,
    agenumber
}

const compRequired<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 {
  namestring,
  agenumber
}

let pReadonly<Company> = {
  name"hello",
  age10
};
// 使用
p.age = 11;
// error  Cannot assign to 'age' because it is a read-only property.

Record

type Property = 'key1' | 'key2'
type Company = Record<Propertystring>;

const p: Company = {
  key1"海康",
  key2"大华",
}

Pick 从某个类型中挑出一些属性出来

type Company = {
  namestring;
  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 {
  namestring,
  agenumber,
  industrystring
}
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 testReturnType<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