TypeScript 基本语法
名词解释
类型注解
作用:相当于强类型语言中的类型声明
语法:(变量/函数): type
,这种语法也叫做类型后置语法
let str: string = 'abc'
联合类型
联合类型(Union Types)表示取值可以为多种类型中的一种。
let count: number | string = 10
枚举
一组有名字的常量集合,可以类比手机里的通讯录。
泛型
泛型可以理解为一个类型层面的函数,泛型变量可以类比函数参数,是代表类型的参数,即类型参数化。不预先确定的数据类型,具体的类型在使用的时候才能确定。
语法
ES6 的数据类型
Boolean
Number
String
undefined
null
Symbol
BigInt
Object
TS 的数据类型
boolean
number
bigint (target 低于 ES2020 时不可用)
string
undefined
null
symbol
array
function
object
void
any
unknown
never
元组
枚举
高级类型
常规类型注解
/*******原始值*******/
const isDone: boolean = false
// 可以使用 number 类型表示 JavaScript 已经支持或者即将支持的十进制整数、浮点数,以及二进制数、八进制数、十六进制数
const amount: number = 6
const integer: number = Number(2)
const binary: number = 0b1010 // 二进制整数
const octal: number = 0o27 // 八进制整数
const hex: number = 0xff // 十六进制整数
const big: bigint = 100n // 大整数,需要 target es2020 及以上
// 所有 JavaScript 支持的定义字符串的方法,我们都可以直接在 TypeScript 中使用
const letter: string = String('S') // 显示类型转换
const address: string = 'beijing' // 字符串字面量
const greeting: string = `Hello World` // 模板字符串
const sym: symbol = Symbol(1)
/*******数组*******/
const list: string[] = ['x', 'y', 'z']
const numList: Array<number> = [1, 2, 3] // 使用 Array 泛型定义数组类型
/*******元组*******/
const name: [string, string] = ['Sean', 'Sun']
/*******枚举*******/
enum Color {
Red,
Green,
Blue,
}
const c: Color = Color.Green
// any 任意类型
let anyTypes: any = 4
anyTypes = 'any'
anyTypes = false
// 空值
function doSomething(): void {
return undefined
}
// 类型断言
let someValue: any = 'this is a string'
let strLength: number = (someValue as string).length
注意:
虽然
number
和bigint
都表示数字,但是这两个类型不兼容。TypeScript 还包含 Number、String、Boolean、Symbol 等类型(注意这些都是首字母大写的),千万别将它们和小写格式对应的 number、string、boolean、symbol 进行等价。基本上我们不会使用到 Number、String、Boolean、Symbol 类型,因为它们并没有什么特殊的用途。这就像我们一般不用 JavaScript 的 Number、String、Boolean 等构造函数 new 一个相应的实例一样。
TS 报错的状态码 2322 是比较常见的,这是静态类型检查的错误码,在注解的类型和赋值的类型不同时会抛出这个错误。
除了 never 类型,可以把 any 类型的值赋值给任意类型的变量。
Interface
TypeScript 中的 Interface 可以看做是一个集合,这个集合是对对象、类等内部结构的约定
// 定义接口 Coords
// 该接口包含 number 类型的 x,string 类型的 y
// 其中 y 是可选类型,即是否包含该属性无所谓
interface Coords {
x: number
y?: string
}
// 定义函数 where
// 该函数接受一个 Coords 类型的参数 l
function where(l: Coords) {
// doSomething
}
const a = { x: 100 }
const b = { x: 100, z: 'abc' }
// a 拥有 number 类型的 x,可以传递给 where
where(a)
// b 拥有 number 类型的 x 和 string 类型的 y1,可以传递给 where
where(b)
// 下面这种调用方式将会报错,虽然它和 where(b) 看起来是一致的
// 区别在于这里传递的是一个对象字面量
// 对象字面量会被特殊对待并经过额外的属性检查(是不是新鲜?)
// 如果对象字面量中存在目标类型中未声明的属性,则抛出错误
where({ x: 100, z: 'abc' })
// 最好的解决方式是为接口添加索引签名
// 添加如下所示的索引签名后,对象字面量可以有任意数量的属性
// 只要属性不是 x 和 y,其他属性可以是 any 类型
interface Coords {
x: number
y?: string
[propName: string]: any
}
接口还常用于约束函数的行为
// CheckType 包含一个调用签名
// 该调用签名声明了 getType 函数需要接收一个 any 类型的参数,并最终返回一个 string 类型的结果
interface CheckType {
(data: any): string
}
const getType: CheckType = (data: any): string => {
return Object.prototype.toString.call(data)
}
getType('abc')
// => '[object String]'
Interface 也可以用于约束类的行为
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface
}
interface ClockInterface {
tick()
}
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute)
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log('beep beep')
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log('tick tock')
}
}
let digital = createClock(DigitalClock, 12, 17)
let analog = createClock(AnalogClock, 7, 32)
除了 ES6 增加的 Class 用法,TypeScript 还增加了 C++、Java 中常见的 public / protected / private 限定符,限定变量或函数的使用范围。
TypeScript 使用的是结构性类型系统,只要两种类型的成员类型相同,则认为这两种类型是兼容和一致的,但比较包含 private 和 protected 成员的类型时,只有他们是来自同一处的统一类型成员时才会被认为是兼容的
class Animal {
private name: string
constructor(theName: string) {
this.name = theName
}
}
class Rhino extends Animal {
constructor() {
super('Rhino')
}
}
class Employee {
private name: string
constructor(theName: string) {
this.name = theName
}
}
let animal = new Animal('Goat')
let rhino = new Rhino()
let employee = new Employee('Bob')
animal = rhino
// Error: Animal and Employee are not compatible
animal = employee
函数类型
函数类型可以先定义再使用,具体实现时就可以不用注明参数和返回值类型了,而且参数名称也不用必须跟定义时相同。
let compute: (x: number, y: number) => number
compute = (a, b) => a + b
类型谓词
在 TypeScript 中,函数支持一种特殊的类型描述。就是在添加返回值类型的地方,通过 “参数名 + is + 类型”的格式明确了参数的类型,进而引起类型缩小,所以类型谓词函数的一个重要的应用场景是实现自定义类型守卫。
function isString(s: any): s is string {
return typeof s === 'string'
}
function isNumber(n: any) {
return typeof n === 'number'
}
function operator(x: unknown) {
if (isString(x)) {
x.toUpperCase() // x 的类型缩小为 string,可以使用 toUpperCase 方法
}
if (isNumber(x)) {
console.log(x) // x 的类型还是 unknown
x.toFixed() // 报错,
}
}
Last updated
Was this helpful?