赞
踩
弱类型
语言,易产生类型错误 ,项目开发时增加了查改 Bug 的时间,影响效率类型支持
功能执行
期做类型检查,代码执行时
发现错误编译
期做类型检查,代码执行前
发现错误;配合 VSCode,代码编写时
发现错误代码提示
,减少查改 Bug 时间,提升开发效率重构代码更加容易
npm i -g typescript
tsc
命令实现 TS => JStsc file.ts
node file.js
ts-node
包,在 Node.js 中执行 TS 代码npm i -g ts-node
ts-node file.ts
类型系统
: number
为变量添加类型约束
let age: number = 18
// 创建类型别名 type Person = { name: string sayHi(): void greet(name: string): void // 普通函数带参数的方法类型 meet: (name: string) => void // 箭头函数带参数的方法类型 } // 使用类型别名作为对象的类型 let person: Person = { name: 'jack', sayHi() {} greet(name) { console.log(name) } meet(name) { console.log(name) } }
let age: number = 18
let myName: string = '老师'
let isLoading: boolean = false
let nu: null = null
let un: undefined = undefined
let smb: symbol = symbol
arrType[]
(推荐)Array<arrType>
// 写法一:
let numbers: number[] = [1, 3, 5]
// 写法二:
let strings: Array<string> = ['a', 'b', 'c']
描述对象结构
{}
描述对象结构key:type
形式fn():type
形式// 空对象 let person: {} = {} // 有属性的对象 let person: { name: string } = { name: '同学' } // 既有属性又有方法的对象 let person: { name: string sayHi(): void } = { name: 'jack', sayHi() {} }
?
表示type Config = {
url: string
method?: string
}
function myAxios(config: Config) {
console.log(config)
}
函数参数
和返回值
的类型// 函数声明
function add(num1: number, num2: number): number {
return num1 + num2
}
// 箭头函数
const add = (num1: number, num2: number): number => {
return num1 + num2
}
函数表达式
可以通过类箭头函数的语法为函数添加类型,声明函数不支持type AddFn = (num1: number, num2: number) => number // 使用 type
const add: AddFn = (num1, num2) => {
return num1 + num2
}
可选参数
?
function mySlice(start?: number, end?: number): void {
console.log('起始索引:', start, '结束索引:', end)
}
|
联合let arr: (number | string)[] = [1, 'a', 3, 'b']
任意类型
起别名type
声明别名,别名推荐使用大写字母开头type CustomArray = (number | string)[]
let arr1: CustomArray = [1, 'a', 3, 'b']
let arr2: CustomArray = ['x', 'y', 6, 7]
对象类型
添加接口interface
声明,接口名称推荐以 I
开头interface IPerson {
name: string
age: number
sayHi(): void
}
let person: IPerson = {
name: 'jack',
age: 19,
sayHi() {}
}
// 为对象类型提供类型接口 interface IPerson { name: string age: number sayHi(): void } // 为对象类型创建类型别名 type IPerson = { name: string age: number sayHi(): void } // 为联合类型创建类型别名 type NumStr = number | string
extends
继承interface Point2D { x: number; y: number }
// 继承 Point2D
interface Point3D extends Point2D {
z: number
}
元素类型
和元素个数
Tuple
// 普通数组,不确定元素个数
let position: number[] = [116.2317, 39.5427]
// 元祖,确定元素类型和个数
let position: [number, number] = [39.5427, 116.2317]
let str1 = 'Hello TS' // let 定义 str1 是变量
let str1: string = 'Hello TS'
const str2 = 'Hello TS' // const 定义 str2 是常量
const str2: 'Hello TS' = 'Hello TS'
明确的可选值列表
// 比如在贪吃蛇游戏中,游戏的方向可选值只能是上、下、左、右
// 使用自定义类型:
type Direction = 'up' | 'down' | 'left' | 'right'
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,会有类型提示:
changeDirection('up')
明确的可选值
,还支持直接使用枚举名称
作为类型注解enum
关键字定义枚举
// 创建枚举
enum Direction { Up, Down, Left, Right }
// 使用枚举类型
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,通过点(.)语法访问枚举 Direction 成员
changeDirection(Direction.Up)
// Down -> 11、Left -> 12、Right -> 13
enum Direction { Up = 10, Down, Left, Right }
enum Direction { Up = 2, Down = 4, Left = 8, Right = 16 }
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
enum Direction { Up = 'UP', Down = 'DOWN', Left = 'LEFT', Right = 'RIGHT' } // 编译为以下 JS 代码 var Direction; (function (Direction) { Direction['Up'] = 'UP' Direction['Down'] = 'DOWN' Direction['Left'] = 'LEFT' Direction['Right'] = 'RIGHT' })(Direction || Direction = {})
函数无返回值
,则使用 void
function greet(name: string): void {
console.log('Hello', name)
}
// 如果什么都不写,此时,add 函数的返回值类型为: void
const add = () => {}
// 这种写法是明确指定函数返回值类型为 void,与上面不指定返回值类型相同
const add = (): void => {}
// 如果指定返回值类型为 undefined,此时,函数体中必须显示的 return undefined 才可以
const add = (): undefined => {
// 此处,返回的 undefined 是 JS 中的一个值
return undefined
}
let obj: any = { x: 0 }
obj.bar = 100
obj()
const n: number = obj
// 变量 age 的类型被自动推断为:number
let age = 18
// 函数返回值的类型被自动推断为:number
function add(num1: number, num2: number) {
return num1 + num2
}
as
关键字实现类型断言,后面补充一个更具体的类型
__proto__
获取 DOM 元素的类型// 返回类型为 HTMLElement,只包含所有标签公共的属性或方法,不包含 a 标签特有的 href 等属性
const aLink = document.getElementById('link')
// 使用类型断言指定更加具体的类型,HTMLAnchorElement 是 HTMLElement 的子类型
const aLink = document.getElementById('link') as HTMLAnchorElement
<>
语法(不推荐)// 在react的jsx中使用会报错
const aLink = <HTMLAnchorElement>document.getElementById('link')
变量或属性类型
(类型查询)let p = { x: 1, y: 2 }
// 简化前
function formatPoint(point: { x: number; y: number }) {}
// 简化后
function formatPoint(point: typeof p) {}
<类型变量 Type>
,即一种特殊类型的变量,相当于类型容器function id<Type>(value: Type): Type { return value }
function id<T>(value: T): T { return value }
<指定类型>
const num = id<number>(10)
const str = id<string>('a')
// 简化泛型函数调用,省略 <指定类型>,TS 进行类型参数推断
let num = id(10)
let str = id('a')
收缩类型
function id<Type>(value: Type[]): Type[] {
console.log(value.length)
return value
}
extends
关键字使用该接口,为泛型添加约束和属性// 创建一个接口
interface ILength { length: number }
// Type extends ILength 添加泛型约束
// 传入类型必须满足 ILength 接口要求,即 number 类型的 length 属性
function id<Type extends ILength>(value: Type): Type {
console.log(value.length)
return value
}
类型变量之间可以约束
function getProp<Type, Key extends keyof Type>(obj: Type, key: Key) {
// keyof Type 获取 person 对象所有键的联合类型,即`'name' | 'age'`
return obj[key]
}
let person = { name: 'jack', age: 18 }
getProp(person, 'name')
// Type extends object:Type 应该是一个对象类型
// 对象类型,应该用 object ,而不是 Object
function getProperty<Type extends object, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key]
}
<类型变量>
Ixxx<类型>
interface IdFunc<Type> {
id: (value: Type) => Type
ids: () => Type[]
}
// 接口中所有成员都可以使用类型变量
let obj: IdFunc<number> = {
id(value) { return value }, // 参数和返回值类型是 number
ids() { return [1, 3, 5] } // 返回值类型是 number[]
}
const strs = ['a', 'b', 'c']
// 鼠标放在 forEach 上查看类型
strs.forEach
const nums = [1, 3, 5]
// 鼠标放在 forEach 上查看类型
nums.forEach
Partial<Type>
type Props = {
id: string
children: number[]
}
// 构造出的新类型 PartialProps 结构和 Props 相同,但所有属性都为可选
type PartialProps = Partial<Props>
Readonly<Type>
type Props = {
id: string
children: number[]
}
// 构造出的新类型 PartialProps 结构和 Props 相同,但所有属性都为只读
type ReadonlyProps = Readonly<Props>
// 错误演示
let props: ReadonlyProps = { id: '1', children: [] }
props.id = '2'
Pick<Type, Keys>
interface Props {
id: string
title: string
children: number[]
}
// 第二个类型变量传入的属性只能是第一个类型变量中存在的属性
// 构造出来的新类型 PickProps,只有 id 和 title 两个属性类型
type PickProps = Pick<Props, 'id' | 'title'>
Omit<K,T>
interface Props {
id: string
title: string
children: number[]
}
// 第二个类型变量传入的属性只能是第一个类型变量中存在的属性
// 构造出来的新类型 OmitProps,只有 children 属性类型
type OmitProps = Omit<Props, 'id' | 'title'>
interface AnyObject {
[key: string]: number
}
let obj: AnyObject = {
a: 1,
b: 2,
}
[key: string]
来约束该接口中允许出现的属性名称。表示只要是 string 类型的属性名称,都可以出现在对象中。key 只是一个占位符
,可以换成任意合法的变量名称。JS 中对象({})的键是 string 类型的
。interface MyArray<T> {
[n: number]: T
}
let arr: MyArray<number> = [1, 3, 5]
[n: number]
来作为索引签名类型。type PropKeys = 'x' | 'y' | 'z'
type Type1 = { x: number; y: number; z: number }
type PropKeys = 'x' | 'y' | 'z'
type Type2 = { [Key in PropKeys]: number }
Key in PropKeys
表示 Key 可以是 PropKeys 联合类型中的任意一个,类似于 forin(let k in obj)。映射类型除了根据联合类型创建新类型外,还可以根据对象类型来创建:
type Props = { a: number; b: string; c: boolean }
type Type3 = { [key in keyof Props]: number }
keyof Props
获取到对象类型 Props 中所有键的联合类型即,‘a’ | ‘b’ | ‘c’。Key in ...
就表示 Key 可以是 Props 中所有的键名称中的任意一个。type Partial<T> = {
[P in keyof T]?: T[P]
}
type Props = { a: number; b: string; c: boolean }
type PartialProps = Partial<Props>
keyof T
即 keyof Props 表示获取 Props 的所有键,也就是:‘a’ | ‘b’ | ‘c’。?
(问号),表示将这些属性变为可选
的,以此来实现 Partial 的功能。T[P] 表示获取 T 中每个键对应的类型
。比如,如果是 ‘a’ 则类型是 number;如果是 ‘b’ 则类型是 string。T[P]
语法,在 TS 中叫做索引访问类型
type Props = { a: number; b: string; c: boolean }
type TypeA = Props['a']
Props['a']
表示查询类型 Props 中属性 ‘a’ 对应的类型 number。所以,TypeA 的类型为 numbertype Props = { a: number; b: string; c: boolean }
type TypeA = Props['a' | 'b'] // string | number
type TypeA = Props[keyof Props] // string | number | boolean
命令:npx create-react-app my-app --template typescript
说明:在命令行中,添加 --template typescript
表示创建支持 TS 的项目
项目目录的变化:
tsconfig.json
.ts
或 .tsx
.ts
ts 文件的后缀名.tsx
是在 TS 中使用 React 组件时,需要使用该后缀react-app-env.d.ts
文件
.d.ts
类型声明文件,用来指定类型tsc --init
生成{ // 编译选项 "compilerOptions": { // 生成代码的语言版本:将我们写的 TS 代码编译成哪个版本的 JS 代码 // 命令行: tsc --target es5 11-测试TS配置文件.ts "target": "es5", // 指定要包含在编译中的 library "lib": ["dom", "dom.iterable", "esnext"], // 允许 ts 编译器编译 js 文件 "allowJs": true, // 跳过类型声明文件的类型检查 "skipLibCheck": true, // es 模块 互操作,屏蔽 ESModule 和 CommonJS 之间的差异 "esModuleInterop": true, // 允许通过 import x from 'y' 即使模块没有显式指定 default 导出 "allowSyntheticDefaultImports": true, // 开启严格模式 "strict": true, // 对文件名称强制区分大小写 "forceConsistentCasingInFileNames": true, // 为 switch 语句启用错误报告 "noFallthroughCasesInSwitch": true, // 生成代码的模块化标准 "module": "esnext", // 模块解析(查找)策略 "moduleResolution": "node", // 允许导入扩展名为.json的模块 "resolveJsonModule": true, // 是否将没有 import/export 的文件视为旧(全局而非模块化)脚本文件 "isolatedModules": true, // 编译时不生成任何文件(只进行类型检查) "noEmit": true, // 指定将 JSX 编译成什么形式 "jsx": "react-jsx" }, // 指定允许 ts 处理的目录 "include": ["src"] }
既包含类型信息又可执行代码
只包含类型信息
的类型声明文件implementation
(代码实现文件);.d.ts 是 declaration(类型声明文件)const strs = ['a', 'b', 'c']
// 鼠标放在 forEach 上查看类型
strs.forEach
lib.es5.d.ts
类型声明文件中lib.dom.d.ts
)node_modules/axios
目录.d.ts
文件提供该类型,实现类型共享let count = 10 let songName = '痴心绝对' let position = { x: 0, y: 0 } function add(x, y) { return x + y } function changeDirection(direction) { console.log(direction) } const fomartPoint = point => { console.log('当前坐标:', point) } export { count, songName, position, add, changeDirection, fomartPoint }
定义类型声明文件
declare let count:number declare let songName: string interface Position { x: number, y: number } declare let position: Position declare function add (x :number, y: number) : number type Direction = 'left' | 'right' | 'top' | 'bottom' declare function changeDirection (direction: Direction): void type FomartPoint = (point: Position) => void declare const fomartPoint: FomartPoint export { count, songName, position, add, changeDirection, FomartPoint, fomartPoint }
yarn add typescript @types/node @types/react @types/react-dom @types/jest
jsconfig.json
改成 path.tsconfig.jsonpath.tsconfig.json
文件,将原来 jsconfig.json
文件中的内容拿过来{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"],
"@scss/*": ["src/assets/styles/*"]
}
}
}
tsconfig.json
中,添加配置{
// 添加这一句
"extends": "./path.tsconfig.json",
"compilerOptions": {
...
}
}
src/react-app-env.d.ts
拷贝到自己项目的 src 目录下.js
、.jsx
(使用 JS 时,React 组件对应的文件后缀).ts
、.tsx
(使用 TS 时,React 组件对应的文件后缀)、.d.ts
.tsx
.ts
或者为其添加类型声明文件 .d.ts
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。