本篇内容不涉及TypeScript安装以及配置,只涉及TypeScript语法相关内容。不讲废话,简单直接。
1、原始类型
const a: string = 'foo'
const b: number = 100
const c: boolean = true
const d: void = undefined
const e: null = null
const f: undefined = undefined
const g: symbol = Symlol()
2、object 类型
object并不单指对象,而是指除了原始类型以外的其他类型
const foo: object = function () {} // [] // {}
const obj: { foo: number,bar: string } = { foo: 123, bar: 'string' }
3、数组类型
// 第一种定义方式,元素类型设置为 *number*
const arr1: Array<number> = [1, 2, 3]
// 第二种定义方式,较为常见
const arr2: number[] = [1, 2, 3]
// 例子
function sum (...args: number[]) {
// 传统做法是要判断传入的参数是否是数字,
而TypeScript中只需要像上面这样对参数做一个类型注解,就行了
return args.reduce(prev, current) => prev + current, 0)
}
sum(1, 2, 3, 'foo') // 这里传入了一个非数字的值就会报错
4、元组类型
元组就是一个明确元素数量 和 明确元素类型 的数组
const tuple: [number, string] = [18, 'foo']
// const tuple: [number, string] = [18, 18] 类型不匹配,会报错
// const tuple: [number, string] = [18, 'foo', 'xxx'] 数量不匹配,会报错
// 访问
const age = tuple[0]
const name = tuple[1]
// 解构
const [age, name] = tuple
5、enum 类型
// enum 对象的属性可以不用赋值,默认从0开始递增,
也可以赋值Draft = 5,后面的就从5开始递增
也可以给具体的值,比如 Draft = 'xxx',这样后面的属性都要给具体的值
enum PostStatus {
Draft = 0,
Unpublished = 1,
Published = 2
}
const post = {
title: 'Hello TypeScript',
content: 'TypeScript is a typed superset of JavaScript.',
status: PostStatus.Draft // 0 // 1 // 2
}
6、函数类型
// 声明式函数
// 参数a和b是number类型,函数返回是string类型,
// 参数后带问号代表是可选参数
// 当参数数量不固定的时候可以使用rest运算符来接受参数,类型是一个值为number的数组
function func1 (a: number, b?: number, ...rest: number[]): string {
return 'func1'
}
// 函数表达式定义函数
const func2 = function (a: number, b: number): string {
return 'func2'
}
// 如果把一个函数作为参数传递,类似callback函数。
function fntD(callback: (bl: boolean) => boolean) {
callback(true)
}
function callback(bl: boolean): boolean {
console.log(bl)
return bl
}
const dResult = fntD(callback)
7、任意类型 any
// value 可以接受任意类型
function stringfy (value: any) {
return JSON.stringify(value)
}
stringify('string')
stringify(10)
stringify(true)
// foo 可以任意赋值
let foo: any = 'string'
foo = 100
8、隐式类型推断
// age 赋值为 number 类型
let age = 18 // number
age = 'string' // 会警告错误,因为age是number类型
let foo // 没有赋值,就是any类型
foo = 100
foo = 'string'
9、类型断言 as
// 假定这个 nums 来自一个明确的接口
const nums = [110, 120, 119, 112]
// 这里TypeScript推断res的类型为 number|undefined
// 因为它并不知道这个i到底在数组中有没有
const res = nums.find(i => i > 0)
// 这里就会报错警告
const square = res * res
// 如果我们直接 断言 这个 res 就是 number 类型
const num1 = res as number
// 这里就不会报错了
const square = res * res
10、接口 interface
接口用来约定对象的结构,一个对象要实现一个接口,就必须拥有这个接口中所包含的所有成员
interface Post {
title: string
content: string
}
function printPost (post: Post) {
console.log(post.title)
console.log(post.content)
}
printPost({
title: 'Hello TypeScript',
content: 'A JavaScript superset'
})
// 特殊的接口成员 可选成员 只读成员
interface Post{
title: string
content: string
subtitle?: string // 加问号就是可选成员
readonly summary: string // 加 readonly 就是只读成员
}
const hello: Post = {
title: 'Hello TypeScript',
content: 'A javascript superset',
summary: 'a javascript'
}
hello.summary = 'other' // 会报错,因为 summary 是只读成员
// 动态成员
interface Cache {
[prop: string]: string
}
const cache: Cache = {}
cache.foo = 'value1'
cache.bar = 'value2'
11、类 Class
Class Person {
// 在这里赋值,和在构造函数中初始化必须两者选其一
name: string // = 'init name' 这里可以直接初始化
private age: number // 这里定义 age 为私有属性
protected gender: boolean // 受保护的类型
readonly national: string // 只读属性,一经初始化,不可更改
constructor (name: string, age: number) {
// 需要在上面标注出构造函数中属性的类型
this.name = name
this.age = age
this.gender = true
this.national = national
}
sayHi (msg: string): void {
console.log(`I am ${this.name}, ${msg}`)
console.log(this.age)
}
}
const tom = new Person('tom', 18)
console.log(tom.name) // tom
console.log(tom.age) // 报错,因为 age 是私有属性,所以访问不到
console.log(tom.gender) // 报错,因为 gender 是受保护的属性,这里访问不到
// 在下方新声明一个类 student 继承与 Person
class Student extends Person {
constructor (name: string, age: number) {
super(name, age)
console.log(this.gender) // 这里就一个访问到 受保护的属性 gender
}
12、类与接口
implements 实现
interface Eat {
eat (food: string): void
}
interface Run {
run (distance: number): void
}
// Person类,实现了 Eat 和 Run 两个接口
class Person implements Eat, Run {
eat (food: string): void {
console.log(`优雅的进餐:${food}`)
}
run (distance: number) {
console.log(`直立行走:${distance}`)
}
}
// Animal类,实现了 Eat 和 Run 两个接口
class Animal implements Eat, Run {
eat (food: string): void {
console.log(`饥不择食的吃:${food}`)
}
run (distance: number) {
console.log(`爬行:${distance}`)
}
}
13、抽象类
abstract 定义抽象类,抽象类只能被继承,不能通过 new 的方式创建实例对象
// 定义一个抽象类 Animal
abstract class Animal {
eat (food: string): void {
console.log(`饥不择食的吃:${food}`)
}
// 定义一个抽象方法 run,可以不需要方法体。
// 定义了抽象方法之后,子类中必须实现这个抽象方法
abstract run (distance: number): void
}
class Dog extends Animal {
run(distance: number): void {
console.log('四脚爬行', distance)
}
}
const d = new Dog()
d.eat('嘎嘎') // 饥不择食的吃:嘎嘎
d.run(100) // 四脚爬行 100
14、泛型 Generics
泛型是指在定义接口函数类的时候,没有指定具体的类型,等到我们在使用的时候再去指定具体的类型的这种特征
// 这里声明一个创建 number 类型数组的函数 creatNumberArray
function createNumberArray (length: number, value: number): number[] {
// 这里的Array是 any 类型,所以要给它指定一个 Number 类型
const arr = Array<number>(length).fill(value)
return arr
}
// 这里声明一个创建 String 类型数组的函数 createStringArray
function createStringArray (length: number, value: string): string[] {
const arr = Array<string>(length).fill(value)
return arr
}
// 因为上面的两个函数代码有冗余,所以这里我们可以使用 泛型
// 一般我们使用 T 来作为泛型参数的名称,然后把函数中不明确的类型都改为 T 来做代表
function createArray<T> (length: number, value: T): T[] {
const arr = Array<T>(length).fill(value)
return arr
}
// 然后使用泛型的时候 传递 T 的类型
const res = creatArray<string>(3,'foo')
// const res = createNumberArray(3, 100)
// res => [100, 100, 100]
基础语法篇到这里结束,更多关于TypeScript的使用请关注我,持续为大家更新。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。