typescript入门级教程

102 阅读7分钟

带着目标学习-原文地址:juejin.cn/post/701880…

一、理解ts的学习目标,相比于js完成了哪些功能,有哪些优势?

对比js

TS是JS的超集,兼容js语法,顾名思义解决js(动态类型)变量类型不确定带来的问题,编译时就发现错误,而不是运行时才报错

TS不能被js解析器解析,需要编译(类似于高版本js编译为低版本js才能被浏览器的js解析器解析)

类比于less、sass之于css

最终需要编译为js,但扩展了原有特性

新特性

扩展了类型 inteface

添加es不具有的新特性 装饰器、接口

丰富的配置选项(严格程度,编译为任意版本的js)

强大的开发工具

优势

学习成本低

减少团队无效沟通

让代码更健壮

二、ts环境搭建

环境搭建(全局安装ts及编译器)

npm i -g typescript ts-node

在工程中创建ts配置文件

ts-node --init

创建ts文件-index.ts

执行该ts文件内容

ts-node index.ts

在线ts练习地址:www.typescriptlang.org/zh/play

三、语法

基础语法-关注类型

对标js的内置类型

let string1: string = "jimmy";

let number1: number = 88;

let boolean1: boolean = false;

let undefined1: undefined= undefined;

let null1: null= null;

let obj1: object = {x: 1};

let bigint1 :bigint = BigInt(100);

let symbol1: symbol = Symbol("hello");

特殊地,默认情况下null和undefined为所有类型的子类型,可以把作为其他类型的值,但tsconfig.json若配置strictNullChecks为true则null和undefined只能赋值给自身类型和void

tips:number和bigint不兼容

typescript中的any编译器开启noImplicitAny,则js写法(不设置类型,等同于设置类型为any)则会引起报错-不允许为any类型

void无任何类型,常用语函数无返回值时设置返回值类型(可被赋予null、undefined但无意义)

never类型,用于检测死循环或者抛出异常

let nev: never  = (()=>{while(true)} ()) 死循环、throw异常 才支持被赋值

 

联合类型

设置数据多个类型,以数组定义为例:

  let arr: (string | number)[] = [ '1,', 2, '3', 4 ]

  let arr1: Array<string | object> = [ 1, '1', { name: 'gpf' } , '2' ]  

  要点:支持自定义类型

  let arrCustom: Array<string | object| customObj> = [1, '1', {name: 'gpf'}, '2']

类型定义-普通类型

  let arr: string[] = [ '1,','3' ]  

强类型约束,类型不同的报错:

  let arr: Array<string | object>[] = ['1,',3]

  - error TS2322: Type 'number' is not assignable to type 'string | object'.

类型定义-函数声明(可选参数、默认值、特殊写法、收集参数)

   function fun1(params1: string, params2: customerObj, params3?:  可选参数): string[] {

let ret: string[] = []

...

return ret

 

支持函数重载,不同类型、数量、顺序的同名函数为重载

 

类型定义-js扩展类型-元组(设置一个形似数组的固定类型集合)

可选参数、默认值、特殊写法、收集参数--同函数

只读元组

 

类型推断-简写方法

很多场景ts会根据上下文自动推断变量类型,const声明的变量例外

/** 根据参数的类型,推断出返回值的类型也是 number /functionadd1(a: number, b: number) { returna + b; } constx1= add1(1, 1); // 推断出 x1 的类型也是 number/* 推断参数 b 的类型是数字或者 undefined,返回值的类型也是数字 */functionadd2(a: number, b = 1) { returna + b; } constx2 = add2(1); constx3 = add2(1, '1'); // ts(2345) Argument of type "1" is not assignable to parameter of type 'number | undefined

声明时没赋值,则被推断为any

 

类型推断-类型断言

  以下greaterThan2执行结果获得number或者undefined,会报ts2322,可采用断言方式可进行强转--as number

  const arrayNumber: number[] = [1, 2, 3, 4];

  const greaterThan2: number = arrayNumber.find(num=> num > 2) as number;

非空断言

let mayNullOrUndefinedOrString: null | undefined | string; mayNullOrUndefinedOrString!.toString(); // ok

 

字面量类型-类似于枚举或者字典,该类型的数据只能取该范围的数据

let obj: 'hello' | 'body' | 'eee'

obj = 'err'

obj = 'hello'

常用形式

interface Config {

size: 'small' | 'big';

isEnable: true | false;

margin: 0 | 2 | 4;

}

  推断造成并不能精确确定类型,此时产生对类型的拓宽与缩小,便于灵活调控类型推断

类型推断-类型拓宽

let yy = 'string'

此时yy被推断为string类型,而不是字面量类型('string', null, undefined, any),因此完全借助类型推断是不行的,必要的地方还必须设置

 

类型推断-类型缩小

结合类型判断

 

type&interface

设置类型别名

type myType1 = string | string[]

function fun(str: myType1): void{}

交叉类型:将类型合并处理

type myTYpe2 = number & string

type IntersectionType= { id: number; name: string; } & { age: number }; constmixed: IntersectionType= { id: 1, name: 'name', age: 18}配合接口实现多接口继承效果

考虑多接口字段名相同 问题--字段类型不兼容(一个strinng、一个 number报错)、若是对象类型,则可以合并

interface

interface Person {

    name: string; // 必选属性

    age?: number; // 可选属性

    [propName: string]: any; //任意属性(属性名任意)

}

约束:其中必备属性必须被设置

开放:可以设置可选属性

开放:可以设置任意属性,但类型要包含必选属性和可选属性

泛型,待进一步研究

ts.config.js

ts的编译配置选项

  • files - 设置要编译的文件的名称;

  • include - 设置需要进行编译的文件,支持路径模式匹配;

  • exclude - 设置无需进行编译的文件,支持路径模式匹配;

  • compilerOptions - 设置与编译流程相关的选项。

    { "compilerOptions": { /* 基本选项 */ "target": "es5", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT' "module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015' "lib": [], // 指定要包含在编译中的库文件 "allowJs": true, // 允许编译 javascript 文件 "checkJs": true, // 报告 javascript 文件中的错误 "jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react' "declaration": true, // 生成相应的 '.d.ts' 文件 "sourceMap": true, // 生成相应的 '.map' 文件 "outFile": "./", // 将输出文件合并为一个文件 "outDir": "./", // 指定输出目录 "rootDir": "./", // 用来控制输出目录结构 --outDir. "removeComments": true, // 删除编译后的所有的注释 "noEmit": true, // 不生成输出文件 "importHelpers": true, // 从 tslib 导入辅助工具函数 "isolatedModules": true, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).

    /* 严格的类型检查选项 */ "strict": true, // 启用所有严格类型检查选项 "noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错 "strictNullChecks": true, // 启用严格的 null 检查 "noImplicitThis": true, // 当 this 表达式值为 any 类型的时候,生成一个错误 "alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'

    /* 额外的检查 */ "noUnusedLocals": true, // 有未使用的变量时,抛出错误 "noUnusedParameters": true, // 有未使用的参数时,抛出错误 "noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误 "noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)

    /* 模块解析选项 */ "moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6) "baseUrl": "./", // 用于解析非相对模块名称的基目录 "paths": {}, // 模块名到基于 baseUrl 的路径映射的列表 "rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容 "typeRoots": [], // 包含类型声明的文件列表 "types": [], // 需要包含的类型声明文件名列表 "allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。

    /* Source Map Options */ "sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置 "mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置 "inlineSourceMap": true, // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件 "inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性

    /* 其他选项 */ "experimentalDecorators": true, // 启用装饰器 "emitDecoratorMetadata": true // 为装饰器提供元数据的支持 } }