前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TypeScript入门

TypeScript入门

作者头像
TagBug
发布2023-03-17 11:37:10
1.4K0
发布2023-03-17 11:37:10
举报
文章被收录于专栏:TagBug

什么是 TypeScript、基本语法、高级类型、工程应用

# TypeScript 入门

# 什么是 TypeScript

# 发展历史

2012-10:微软发布了 TypeScript 第一个版本 (0.8)

2014-10:Angular 发布了基于 TypeScript 的 2.0 版本

2015-04:微软发布了 Visual Studio Code

2016-05:@types/react 发布,TypeScript 可开发 React

2020-09:Vue 发布了 3.0 版本,官方支持 TypeScript

2021-11:v4.5 版本发布

# 特点

JS:动态类型、弱类型

TS:静态类型、弱类型

JS 的本质是脚本语言,当被执行时才会匹配类型

TS 是不能被直接执行的,会在执行前进行类型匹配,编译后才能执行

# 优势

  1. 静态类型: 可读性增强:基于语法解析 TSDoc,ide 增强 可维护性增强:在编译阶段暴露大部分错误 => 多人合作的大型项目中,获得更好的稳定性和开发效率
  2. JS 的超集: 包含于兼容所有 JS 特性,支持共存 支持渐进式引入与升级

# 基本语法

# 基础数据类型

代码语言:javascript
复制
/* 字符串 */
const q: string = 'string';
/* 数字 */
const w: number = 1;
/* 布尔值 */
const e: boolean = true;
/* null */
const r: null = null;
/* undefined */
const t: undefined = undefined;

# 对象类型

代码语言:javascript
复制
const bytedancer: IBytedancer = {
    jobId: 9303245,
    name: 'Lin',
    sex: 'man',
    age: 28,
    hobby: 'swimming',
}

interface IBytedancer {
    /* 只读属性:约束属性不可在对象初始化外赋值 */
    readonly jobId: number;
    name: string;
    sex: 'man' | 'woman' | 'other';
    age: number;
    /* 可选属性:定义该属性可以不存在 */
    hobby?: string;
    /* 任意属性:约束所有对象属性都必须是该属性的子类型 */
    [key: string]: any;
}

/* 报错:无法分配到 "jobId",因为它是只读属性 */
bytedancer.job1d = 12345;
/* 成功:任意属性标注下可以添加任意属性 */
bytedancer.plateform = 'data ';
/* 报错:缺少属性 "name", hobby 可缺省 */
const bytedancer2: IBytedancer = {
    jobId: 89757,
    sex: 'woman',
    age: 18,
}

# 函数类型

代码语言:javascript
复制
function add(x: number, y: number): number{
    return x + y;
}

const mult: (x: number, y: number) => number = (x, y) => x * y;

# 函数重载

代码语言:javascript
复制
/* 对 getDate 函数进行重载,timestamp 为可缺省参数 */
function getDate(type: 'string ' , timestamp?: string): string;
function getDate(type: 'date' , timestamp? : string): Date;
function getDate(type: 'string' | 'date', timestamp?: string): Date | string {
    const date = new Date(timestamp);
    return type === 'string' ? date.toLocaleString() : date;
}

const x = getDate( 'date' ); // x: Date
const y = getDate( 'string', '2018-01-10' ); //  y: string

代码语言:javascript
复制
interface IGetDate {
    (type: 'string' , timestamp?: string): string;
    (type: 'date', timestamp? : string): Date;
    (type: 'string' | 'date ', timestamp?: string): Date | string;
}

/* 不能将类型 "(type: any,timestamp: any) => string | Date" 分配给类型 "IGetDate"。
不能将类型 "string | Date" 分配给类型 “string”。
不能将类型 "Date" 分配给类型 “string"。ts (2322) */
const getDate2: IGetDate = (type, timestamp) => {
    const date = new Date(timestamp)
    return type == 'string' ? date.toLocaleString() : date;
}

# 数组类型

代码语言:javascript
复制
/*「类型+方括号」表示 */
type IArr1 = number[];
/* 泛型表示 */
type IArr2 = Array<string | number | Record<string,number>>;
/* 元祖表示 */
type IArr3 = [number, number, string, string]; 
/* 接口表示 */
interface IArr4 {
    [key: number] : any;
}

const arr1: IArr1 = [1, 2, 3, 4, 5, 6];
const arr2: IArr2 = [1, 2, '3', '4', { a: 1 }];
const arr3: IArr3 = [1, 2, '3', '4'];
const arr4: IArr4 = ['string', () => null, {}, []];

# 泛型

代码语言:javascript
复制
function getRepeatArr(target) {
    return new Array(100).fill(target);
}

type IGetRepeatArr = (target: any) => any[];

/* 不预先指定具体的类型,而在使用的时候再指定类型的一种特性 */
type IGetRepeatArrR = <T>(target: T) => T[];

代码语言:javascript
复制
/* 泛型接口 & amp; 多泛型 */
interface IX<T,U>{
    key: T;
    val: U;
}
/* 泛型类 */
class IMan<T> {
    instance: T;
}
/* 泛型别名 */
type ITypeArr<T> = Array<T>;

代码语言:javascript
复制
/* 泛型约束:限制泛型必须符合字符串 */
type IGetRepeatStringArr = <T extends string>(target: T) => T[];
const getStrArr: IGetRepeatStringArr = target => new Array(100).fill(target);
/* 报错:类型 "number” 的参数不能赋给类型"string" 的参数 */
getStrArr(123);

/* 泛型参数默认类型 */
type IGetRepeatArr<T = number> = (target: T) => T[];
const getRepeatArr: IGetRepeatArr = target => new Array(100).fill(target);
/* 报错:类型 “string"的参数不能赋给类型"number" 的参数 */
getRepeatArr('123');

# 类型别名 & 类型断言

代码语言:javascript
复制
/* 通过 type 关键字定义了 I0bjArr 的别名类型 */
type IObjArr = Array<{
    key: string;
    [objKey: string] : any;
}>

function keyBy<T extends IObjArr>(objArr: Array<T>) {
    /* 未指定类型时,result 类型为 {(}*/
    const result = objArr.reduce(( res, val, key) => {
        res [key] = val;
        return res;
    },{});
    /* 通过 as 关键字,断言 result 类型为正确类型 */
    return result as Record<string,T>;
}

# 高级类型

# 联合 / 交叉类型

常规写法:繁琐且不准确

代码语言:javascript
复制
interface IHistoryBook {
    author: string;
    type: string;
    range: string}
interface IStoryBook {
    author: string;
    type: string;
    theme: string;
}

type IBookList = Array<IHistoryBook | IStoryBook>;

联合和交叉类型:

联合类型:IA IB;联合类型表示一个值可以是几种类型之一

交叉类型:IA & IB;多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性

代码语言:javascript
复制
type IBookList = Array<{
    author: string;
} & ({
    type: 'history';
    range: string;
} | {
    type: 'story';
    theme: string;
})>

# 类型保护与类型守卫

代码语言:javascript
复制
interface IA { a: 1, a1: 2 }

interface IB { b: 1, b1: 2 }

function log(arg: IA|IB){
    /* 报错:类型 “IA│IB"上不存在属性"a"”。类型 “IB” 上不存在属性 “a" */
    /* 结论:访问联合类型时,处于程序安全,仅能访问联合类型中的交集部分 */
    if (arg.a) {
        console.log(arg.a1)
    } else {
        console.log(arg.b1);
    }
}

/* 类型守卫:定义一个函数,它的返回值是一个类型谓词,生效范围为子作用域 */
function getIsIA(arg: IA |IB) : arg is IA {
    return !!(arg as IA).a;
}

function log2(arg: IA | IB){
    if (getIsIA(arg)){
        console.log(arg.a1)
    } else {
        console.log(arg.b1);
    }                          
}

# 高级类型

代码语言:javascript
复制
interface IMerge {
    <extends Record<string,any>>(sourceObj: Partial<T>, targetObj: T):T;
}

type IPartial<T extends Record<string,any>> = {
    [P in keyof T]?: T[P];
}

// 索引类型:关键字【keyof】,其相当于取值对象中的所有 key 组成的字符串字面量,如
type IKeys = keyof { a: string; b: number }; // = >type IKeys = "a"|"b"“

// 关键字【in】,其相当于取值字符串字面量中的一种可能,配合泛型 P,即表不母个 key

// 关键字【?】,通过设定对象可选选项,即可自动推导出子集类型

# 函数返回值类型

代码语言:javascript
复制
type IDelayCall = <T extends () =>any>(func: T) => ReturnType<T>;
type IReturnType<T extends (...args: any) => any> = T extends (...args: any)>infer R? R: any

// 关键字【extends】跟随泛型出现时,表示类型推断,其表达可类比三元表达式
// 如: T == 判断类型?类型 A: 类型 B
    
// 关键字【infer】出现在类型推荐中,表示定义类型变量,可以用于指代类型
// 如该场景下,将函数的返回值类型作为变量,使用新泛型 R 表示,使用在类型推荐命中的结果中

# 工程应用

  1. Webpack 在 webpack 中导入 awesome-typescript-loader、babel-loader,配置 tsconfig.js 文件
  2. Node.js 使用 npm 安装 tsc,配置 tsconfig.js,运行 tsc 编译 ts 文件
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-012,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • # TypeScript 入门
    • # 什么是 TypeScript
      • # 发展历史
      • # 特点
      • # 优势
    • # 基本语法
      • # 基础数据类型
      • # 对象类型
      • # 函数类型
      • # 函数重载
      • # 数组类型
      • # 泛型
      • # 类型别名 & 类型断言
    • # 高级类型
      • # 联合 / 交叉类型
      • # 类型保护与类型守卫
      • # 高级类型
      • # 函数返回值类型
    • # 工程应用
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档