# 环境配置

# 安装全局TypeScript

npm install -g typescript

# 创建环境

查看支持命令

tsc --help

初始化

tsc --init

# TS基础知识

# 原始类型

  • boolean、number、string、undefined、null、symbol、void、bigint

小写表示ts的类型,大写的Boolean、Number、String是 JavaScript 的构造函数

  • void表示空类型

在js中void表达式的返回结果是undefined

  • symbol唯一不变的,需要es6的支持
  • bigint大整数新类型,大于Number.MAX_SAFE_INTEGER,数字类型后面需要加n

# 其他类型

  • any 任意类型

经常any的时候,typescript就进化成了anyscript,尽量不要使用

  • unkonw 任意类型,相对any安全,被确定是某个类型之前,不能实例化,访问属性,函数执行
  • never永不存在的,任何其他类型不能赋值给never,常用于函数返回值和空数组
  • 数组,泛型类型,需要指定里面每个元素的类型 Array<number>或number []
  • 元组,已知元素数量和类型的数组,各元素类型不必相同,[string, number]
[string, number]=>
interface Tuple extends Array<string | number> {
  0: string,
  1: number,
  length: 2
}
  • enum枚举,用于声明一组命名的常数,当一个变量有几种可能的值时
    • 数字枚举,值会递增
    • 字符串枚举
    • 反向映射功能,key=>value,key<=>value,值得深思
    • 分开枚举,自动合并
  • object表示非原始数据类型,普通对象、枚举、数组、元组通通都是 object 类型

# 接口

TypeScript 的核心原则之一是对值所具有的结构进行类型检查,接口的作用就是定义这些结构,我喜欢称接口为自定义数据类型,比如ajax返回的结果,事件对象,react中的state和props等等

interface AjaxType{
    code: number,   // 普通属性
    data?: AjaxType,  // 可有可无的属性
    readonly msg: string // 只读属性
}   

interface PropsType{
    handleClick: (e: React.NativeEvent)=>never, // 函数声明
    [propName: string]: any // 字符串索引签名
}
  • 接口可以继承和多重继承
interface BW{
    [name: key]: string
}
interface Program{
    env: string,
    language: string [],
    tool: string []
}
interface WZ extedns BW,Program{
    target: string
}

#

  • 访问限定符
    • private, 只可以在类的内部访问
    • protected,只可以在类的内部及子类访问
    • public,默认为public,可以在类的内部和外部访问
  • Class作为接口,用于porps的类型检查的defaultProp的默认值
    • 接口是规范,只声明成员方法不做实现
    • 类声明成员方法并可以赋值

# 函数

  • 定义函数类型
const add: (a:number, b:number)=>number = (a:number, b:number)=>a+b
  • 函数重载,用同样的函数名声明不同参数和类型的函数

# 泛型

在使用时指定类型,最简单的泛型就是数组

  • 函数中的泛型
function swap<T, U>(tuple: [T, U]): [U, T] {
    return [tuple[1], tuple[0]];
}

swap('hello', 'world')
  • 泛型接口
interface PropsType<T, U>{
    (e: T): U
}
  • 泛型栈
// 泛型栈
class Stack<T> {
    private arr: T[] = []

    public push(item: T) {
        this.arr.push(item)
    }

    public pop() {
        this.arr.pop()
    }
}
  • 泛型约束
function pick<T, K extends keyof T>(o: T, names: K[]): T[K][] {
    return names.map(n => o[n]);
}
// K extends keyof T 约定前者属于后者
  • 泛型约束与索引类型
function getValue<T extends object, U extends keyof T>(obj: T, key: U) {
  return obj[key] // ok
}
  • 继承交叉类型
T extends FirstInterface & SecondInterface & ThirdInterface
  • 构造函数类泛型,需要使用到new()
function factory<T>(type: {new(): T}): T {
  return new type() // ok
}

# 类型断言

当我们知道某些数据会变成某个类型的时候,可以使用as做类型断言,比如ajax请求来的数据符合我们的State中的一个属性

interface ItemType{
    id: string,
    price: num,
    src: string
}
interface StateType{
    item: ItemType []
}
this.setState({
    item: data.data.item as ItemType []
})
  • 双重断言
A as any as B

# 交叉类型&联合类型&类型别名

  • 交叉类型 &, 将多个类型合并为一个类型
  • 联合类型 |, 属性为多种类型之一
  • 类型别名 type, 创建类型别名,可以是普通类型,交叉类型或联合类型
  • 类型别名跟interface的区别
    • interface 只能用于定义对象类型
    • interface 可以实现接口的extends和implements
    • type 可以定义更多类型

# 模块与命名空间

  • 命名空间
    • 目的是解决重名问题
    • 本质是一个对象
namespace React{
    function createElement<P extends {}>(
        type: FunctionComponent<P>,
        props?: Attributes & P | null,
        ...children: ReactNode[]): FunctionComponentElement<P>;
    interface ComponentLifecycle<P, S, SS = any> extends NewLifecycle<P, S, SS>, DeprecatedLifecycle<P, S> {
        /**
         * Called immediately after a component is mounted. Setting state here will trigger re-rendering.
         */
        componentDidMount?(): void;
        /**
         * Called to determine whether the change in props and state should trigger a re-render.
         *
         * `Component` always returns true.
         * `PureComponent` implements a shallow comparison on props and state and returns true if any
         * props or states have changed.
         *
         * If false is returned, `Component#render`, `componentWillUpdate`
         * and `componentDidUpdate` will not be called.
         */
        shouldComponentUpdate?(nextProps: Readonly<P>, nextState: Readonly<S>, nextContext: any): boolean;
        /**
         * Called immediately before a component is destroyed. Perform any necessary cleanup in this method, such as
         * cancelled network requests, or cleaning up any DOM elements created in `componentDidMount`.
         */
        componentWillUnmount?(): void;
        /**
         * Catches exceptions generated in descendant components. Unhandled exceptions will cause
         * the entire component tree to unmount.
         */
        componentDidCatch?(error: Error, errorInfo: ErrorInfo): void;
    }
}
  • 模块与命名空间的区别
    • 命名空间在全局具有唯一性,可以跨文件
    • 模块以文件为单位,每个单独的文件是一个模块

# 常用函数

# Omit:去除类型中某些项

Omit<type,string>,参数:第一个为继承的type类型,第二个为想要的key的字符串,多个字符串用|分开,返回去除类型中某些项的type

/**
 * Construct a type with the properties of T except for those in type K.
 */
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

interface Contact{
  name: string;
  phone?: string; 
  avatar: string;
  userid: string;
  email: string;
}
export type OmitEmailContact = Omit<Contact, 'email' >;
OmitEmailContact{
  name: string;
  phone?: string; 
  avatar: string;
  userid: string;
}

export type OmitEmailAvatarContact = Omit<Contact, 'email' | 'avatar'>;
OmitEmailAvatarContact {
  name: string;
  phone?: string; 
  userid: string;
}

# Pick: 选取类型中指定类型

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

export interface ContactPick extends Pick<Contact, 'name' | 'phone'> {}
ContactPick {
  name: string;
  phone?: string; 
}

# Partial: 将类型中所有选项变为可选

/**
 * Make all properties in T optional
 */
type Partial<T> = {
    [P in keyof T]?: T[P];
};

export interface PartialContact = Partial<Contact>
PartialContact{
  name?: string; // 姓名
  phone?: string; // 手机号
  email?: string; // 邮箱
  avatar?: string; // 头像
  userid?: string; // id
}

# Required: 将类型中所有选项变为必选,去除所有?

/**
 * Make all properties in T required
 */
type Required<T> = {
    [P in keyof T]-?: T[P];
};

export interface RequiredContact= Required<Contact>
RequiredContact{
  name: string; // 姓名
  phone: string; // 手机号
  email: string; // 邮箱
  avatar: string; // 头像
  userid: string; // id
}

# Exclude<T, U>: 取两者交集

type Exclude<T, U> = T extends U ? never : T;

interface StoreInfo {
    order_date: string 
    record_date: string 
    delivery_date: string 
    createdAt_date: string
}

Exclude<StoreInfo, "order_date" | "record_date" | "sign_time"> 
// sign_time

# Extract<T, U>: 取两者差集

type Extract<T, U> = T extends U ? T : never;

interface StoreInfo {
    order_date: string 
    record_date: string 
    delivery_date: string 
    createdAt_date: string
}

Extract<StoreInfo, "order_date" | "record_date" | "sign_time">
// order_date
上次更新: 2021/12/13下午3:57:57