Typescript快速入门

Typescirpt

想必大家已经知道Typescript有什么作用了,话不多说,直接开整,
此文为本人入门学习笔记,有谬误和缺漏欢迎指出

基本使用

八大类型
let str: string = "jimmy";
let num: number = 24;
let bool: boolean = false;
let u: undefined = undefined;
let n: null = null;
let obj: object = {x: 1};
let big: bigint = 100n;
let sym: symbol = Symbol("me"); 

// 注意
// 大写首字母,指的是包装类型
let isDoneToo: Boolean = new Boolean(1)
// console.log(typeof isDoneToo); // object

类型扩宽
看了上面基础使用的小伙伴肯定心里犯嘀咕了. 这么麻烦?定义一个变量就要写一次类型,这不得累死. 而且const 又不用修改,类型一目了然,
接下来我们介绍 类型扩宽

let str1 = "this is string" // 类型是 string
const str2 = "this is string" // 类型是 "this is string" 

注意观察 st1 和 str2 类型不同

// 这个东西有什么用呢? 举个例子:
function getComponent(axis: 'x' | 'y' | 'z') {
    return axis
}
let y = 'y'
getComponent(y) // 类型“string”的参数不能赋给类型“"x" | "y" | "z"”的参数。ts(2345)

// 需要把let 改成 const , const 的类型是 'y',才符合要求


// 使用 const 类型断言, 取消类型扩宽
// Type is { x: number; y: number; }
const obj1 = { 
  x: 1, 
  y: 2 
}; 

// Type is { x: 1; y: number; }
const obj2 = {
  x: 1 as const,
  y: 2,
}; 

// Type is { readonly x: 1; readonly y: 2; }
const obj3 = {
  x: 1, 
  y: 2 
} as const;
void

用来表示没有任何返回值的函数

let a: void = undefined

function fnn(): void { }
never

表示永远不会存在值的类型

function fnnn(): never {
    while (true) {
    }
}

// 用法
// 利用 never 类型的特性来实现全面性检查
type Foo = string | number;
function handleValue(foo: Foo) {
    if (typeof foo === "string") {
        // 这里 foo 被收窄为 string 类型
    } else if (typeof foo === "number") {
        // 这里 foo 被收窄为 number 类型
    } else {
        // 永远到达不了
        const check: never = foo;
        // 如果达到这里就会报错, 因为 never类型不能赋值
    }
}
Never 和 Void 的 区别

虽然他们看上去没什么区别,都可以用于描述函数没有返回值

但我们默认 没有显式返回值的函数会隐式返回 undefined 。 注意: never类型可以被undefined 赋值

具有never返回类型的函数永不返回,它也不返回 undefined。 注意: 返回never的函数必须存在无法达到的终点

unknown

用来描述我们不知道类型的变量

let maybe: unknown
maybe = 1
maybe = '2'
maybe = {}
Unknow 和 Any 的区别

推荐使用unknown, 如果是any类型, 相当于放弃了类型检查

let maybe2: unknown;

maybe2 = [1, 2, 3, 4]
// console.log(maybe2.length); // 报错报错报错. 必须进行类型收窄, 如果maybe2 是 any类型就不会报错

if (maybe2 instanceof Array) {
    // console.log(maybe2.length);   // 4
}
类型断言
// 尖括号 语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

// as 语法
let someValue1: any = "this is a string";
let strLength2: number = (someValue1 as string).length;
联合类型
let b: string | number

function say(age: string | number) {
    age.toString()
    // age.length  // 报错,当ts不确定是哪种类型, 此时只能访问联合类型共有的属性和方法
    // 当变量赋值后, 会根据类型推断出一个类型
}
数组的类型

类型 + []

数组项中不能出现其他类型, 调用方法添加也不行

const list: number[] = [1, 2, 3]
// 针对一些复杂的数组, 我们可以通过any 来表示数组中允许出现任意的类型
const listTwo: any[] = ['1', 2, { username: 'nzk', age: 18 }]

interface Arrobj{
    name:string,
    age:number
}
let arr3:Arrobj[]=[{name:'jimmy',age:22}]

// 联合类型的数组
let arr:(number | string)[];
// 表示定义了一个名称叫做arr的数组, 
// 这个数组中将来既可以存储数值类型的数据, 也可以存储字符串类型的数据
arr = [1, 'b', 2, 'c'];

数组泛型写法

const listThree: Array<string> = ['1', '2', '3']

接口表示

interface NumberArray {
    [index: number]: number
}
const list4: NumberArray = [1, 2, 3]

元组(Tuple)
const Tuple: readonly[number, string, boolean?, ...object[]] = [1, '2', true, {}, {}, {}]
枚举 (enum )
// 会自动递增
enum Days {
    Mon = 1,
    Tue,
    Wed,
    Thu,
    Fri,
    Sat,
    Sun,
}

Days['Mon'] // 1

Days['Sun'] //7

// 常量枚举
const enum Month {
    Jan,
    Feb,
    Mar,
    // April = '123'.length // 会报错, 计算项不能出现在常量枚举中
}

// 外部枚举
declare enum Directions {
    Up,
    Down,
    Left,
    Right
}
类型 (type)

type 和 interface 的区别

type

  • 不允许同名, 扩展已有的 type 需要创建新 type

interface

  • 同名会合并

  • 只能表示 objectclassfunction 类型

接口 interface
interface Duck {
    // 只读属性,不能修改
    readonly id: number,
    name: string
    age: number
    // 可选属性
    gender?: boolean
    walk: Function
    //任意属性 如果定义了任意属性,那么上面确定属性和可选属性必须是它的子集
    [propName: string]: string | number | boolean | Function | undefined
}

const dog: Duck = {
    id: 1,
    name: '乌子',
    age: 11,
    walk() { },
    color: 'red'
}

函数的类型
const sum = function (x: number, y: number): number {
    return x + y
}
// 上面的 sum 左侧是类型推导出来的
// 手动添加类型如下所示
// 这里的 => 与es6的箭头不同, ts 中 => 用来表示函数的定义, 左边是输入类型, 右边是输出类型

const sumCopy: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y
}

或使用接口

interface ISumFunc {
    (firstName: string, lastName?: string): string
}

const buildName: ISumFunc = (firstName, lastName) => firstName + '' + lastName

剩余参数

设有默认值的参数,默认为可选参数

通过…rest 的方式获取函数中剩余的参数, 它只能作为函数的最后一个参数

function getRest(first: any = '999', ...rest: any[]) {
    rest.map(el => { })
}

getRest(1, 2, 3, 4, 5, 6)
函数重载
function add(x: number, y: string): void
function add(x: string, y: number): void
function add(x: string | number, y: number | string): void { }


add(1, '1')

add('2', 2)

// add('2', '2') 报错,传入的参数必须符合前面的定义

泛型

T 类型 K 键 V值

泛型就是解决 类 接口 方法的复用性, 以及对不特定数据类型的支持(类型校验)

function getData<T>(value: T): T {
    return value
}

console.log(getData<number>(123));// 调用的时候给泛型写上类型
getData(123) // 也可以不写,自动推断
typeof
// 在类型上下文中获取变量或者属性的类型

const sem: Person = { name: "nzk", age: 30 }

type Sem = typeof sem // type Sem = Person

const semTwo = { name: "nzk", age: 30 }

type SemTwo = typeof semTwo
// type SemTwo = {
//     name: string;
//     age: number;
// }
// 它也可以用来获取函数对象的类型
keyof

该操作符可以用于获取某种类型的所有键,其返回类型是联合类型。

// 使用keyof
function propTwo<T extends object, K extends keyof T>(obj: T, key: K) {
    return obj[key]
}

type Any = keyof any // type Any = string | number | symbol
in

in用来遍历枚举类型

type Keys = 'a' | 'b' | 'c'

type Obj = {
    [p in Keys]: string
}
/*
type Obj = {
    a: string;
    b: string;
    c: string;
}
*/

infer

用于占位

type ReturnType<T extends (...any: any) => any> = 
T extends (...any: any) => infer R ? R : any

type Parameters<T extends (...param: any) => any> = 
T extends (...param: infer P) => any ? P : any

// 以上两个工具类型, 通过 infer 占位设置一个泛型 获取到了参数或返回值的类型, 用于获取未知的类型

// 将元组转化成联合类型
type ElementOf<T> = T extends Array<infer E> ? E : never

type TTuple = [string, number]

type ToUnion = ElementOf<TTuple>  // string | number


extends

映射类型
interface TestInterface {
    name?: string,
    age?: number
}
// 通过+/-来指定添加还是删除
type OptionalTestInterface<T> = {
    readonly [p in keyof T]-?: T[p]
}
type newTestInterface = OptionalTestInterface<TestInterface>
/* 
type newTestInterface = { // 所有类型都变成必选,只读
    readonly name: string;
    readonly age: number;
}
*/
内置工具类型

由于一些功能需求比较常见, ts内置一些工具类型

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

interface UserInfo {
    id: string,
    name: string,
    age: number,
    love: string
}
type NewUserInfo = Partial<UserInfo>  // 所有属性变为可选
const xiaoming: NewUserInfo = {
    name: 'nzk'
}

// 一个递归的 Partial 

type DeepPartial<T> = {
    // 如果是 object,则递归类型
    [U in keyof T]?: T[U] extends object
    ? DeepPartial<T[U]>
    : T[U]
};

// type PartialedWindow = DeepPartial<T>; // 现在T上所有属性都变成了可选啦
Required

Partial同理

Readonly

partial同理

Pick

从某个类型中取出一些属性形成一个新的类型

type MyPick<T, K extends keyof T> = {
    [P in K]: T[P]

}

type NewNzkINfo = MyPick<UserInfo, 'id' | 'name'>
/*
type NewNzkINfo = {
    id: string;
    name: string;
}
*/
const nzk: NewNzkINfo = {
    id: '1',
    name: 'nzk'
}
Record

Record <作为K的type, 作为Value的type> 形成一个新的类型

type Any = keyof any // type Any = string | number | symbol

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


interface PageInfo {
    title: string
}

type Page = "home" | "about" | "contact"
/*
 Record <作为K的type, 作为Value的type>
*/
type Xone = Record<Page, PageInfo>
/* type Xone = {
    home: PageInfo;
    about: PageInfo;
    contact: PageInfo;
} */
const xone: Xone = {
    about: { title: "aaaa" },
    contact: { title: "cccc" },
    home: { title: "hhhh" },
}

Omit
/*
Omit<T, K extends keyof any> 的作用是使用 T 类型中除了 K 类型的所有属性,来构造一个新的类型。

 简单说就是删除一(多)个属性
*/

type MyOmit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;


interface Todo {
    title: string;
    description: string;
    completed: boolean;
}

type TodoPreview = Omit<Todo, "description">;

const todoTwo: TodoPreview = {
    title: "Clean room",
    completed: false,
};

/*
步骤分解
*/
// 先使用 Exclude 删掉 Todol联合类型中的 description 
type step1 = Exclude<keyof Todo, 'description'> // type step1 = "title" | "completed"
// 再使用 Pick将 剩下的联合类型组成需要的类型别名
type step2 = Pick<Todo, step1>
/* 
type step2 = {
    title: string;
    completed: boolean;
}
 */

ReturnType

获取函数的返回值类型

type ReturnType<T extends (...args: any[]) => any> 
= 
T extends (...args: any[]) => infer R ? R : any;
Parameters

获取函数类型中的参数部分,作为一个元组返回

const fn1 = (name:string,age:number,love?:string) => {
    return {
        name,
        age
    }
}
type Fn2 = Parameters<typeof fn1>
// type Fn2 = [name: string, age: number, love?: string | undefined]
const fn2 = ([name,age]:Fn2) =>{
    const username = "名字" + name
    fn1(username,age)
}

class Person{
    name: string = "孙悟空"
    static subName: string = "美猴王" // 静态属性 访问必须要通过 Person
    static get init ():void { // 带get的会立即执行 ???
        console.log("立即执行")
    }
}
Person.subName
Person.init

在类的方法中,super表示当前类的父类

继承时,必须要写super(); 如果父类有参数

constructor(父类xxx:string){
    super(父类xxx)
}
类的继承,详情见 /TS/day01/src/.ts

abstract:开头的类是抽象类,只能用于继承,不能实例化

public:公有属性

private:私有属性,属性名前加 private 禁止被修改 只能在内部访问,如果要访问和修改,都得通过方法

protected: 保护类型, 只有当前类和子类能访问, 外部不能访问

装饰器

function logClass(param: string) {
    // param 是当前的类
    // param.prototype.apiUrl = "动态扩展的属性"
    return function(target:any){ // 装饰器工厂
        console.log(target);
        console.log(param);
    }

}

@logClass('hello')
class Http {
    value: number
    constructor(value: number) {
        this.value = value
    }
}


const http = new Http(1)
console.log(http);

其他

.d.ts

JS文件 + .d.ts文件 === ts文件

.d.ts 文件可以让JS文件继续维持自己JS文件的身份, 而拥有TS的类型保护.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值