编程语言有以下两种类型:
JS
/ Python
)c++
/ c
/ c#
/ java
)TS 的特点:
es6
到es10
甚至是esnext
的语法支持新建 test.ts
文件
const hello = (name:string) => {
return `Hello ${name}`
}
hello('Axton Tang')
使用 tsc
命令进行编译成 js 文件
该函数要求传入的参数为 string
类型,如何传入其他类型,编译则会报错
Any
类型let isDone: boolean = true
let age: number = 20
let firstName: string = 'Axton'
let message: string = `hello ${firstName}`
message = null // null 和 undefined 是任何类型的子类型
let n: null = null
let u: undefined = undefined
let notSure: any = 20 // 当不确定传入的参数是什么类型时,可以用 any (不建议使用)
notSure = 'maybe a string'
notSure = true
notSure.myName
notSure.getName()
let arrOfNumber: number[] = [1,2,3] //定义number类型的数组
arrOfNumber.push(3)
function test () {
console.log(arguments) //类数组
}
let user: [string, number] = ['Axton', 20] // 定义元组,与数据类型只能一一对应
user.push('Tang') // 只能是上面两种数据类型之一
对对象的形状进行描述
interface Person {
name: string, //定义接口的属性
age?: number //如何该属性可选就可以改为 '?:' 这样如何实现该属性也不会报错
readonly sex: string //设置只读属性
}
let Axton: Person = { //声明变量, 实现这个接口
name: 'Axton Tang', // 必须与接口的属性一致
age: 20,
sex: '男'
}
const add = (x: number, y:number, z?: number): number => {
if (typeof z === 'number') {
return x+y+z
} else {
return x+y
}
}
add(1,2,3)
interface ISum { //用接口来描述函数类型
(x: number, y: number, z?: number): number
}
let add2: ISum = add
1、类型推论: 在没有明确指明变量的类型时,TS 会根据你第一次的赋值推测出这个变量的类型,之后再进行赋值成其他类型会报错
2、联合类型:
当变量是联合类型时,只能使用联合类型共有的属性和方法
let str = 'string'
// 联合类型
let numberOrString: number | string
numberOrString = 123
numberOrString = 'Axton'
3、类型断言:
// 由于使用联合类型后只能用共有属性和方法,但是有时候想用特有的方法,就可以使用类型断言
// 方法一
function getLength(input: string | number): number {
const str = input as string // 注意: 此处并不是把它转化成这个类型
if (str.length) {
return str.length
} else {
const number = input as number
return number.toString().length
}
}
// 方法二
//type guard
function getLength2(input: string | number): number {
if (typeof input === 'string') { // 使用条件判断会自动缩小范围,可以使用该类型特有方法
return input.length
} else {
return input.toString().length
}
}
class Animal {
readonly name: string;
constructor(name) {
this.name = name
}
run() {
return `${this.name} is running`
}
}
const snake = new Animal('lily')
console.log(snake.run())
class Dog extends Animal {
bark() {
return `${this.name} is barking`
}
}
const xiaobao = new Dog('xiaobao')
console.log(xiaobao.run())
console.log(xiaobao.bark())
class Cat extends Animal {
static categories = ['mammal']
constructor(name) {
super(name)
console.log(this.name)
}
run() {
return 'Meow, ' + super.run()
}
}
const maomao = new Cat('maomao')
console.log(maomao.run())
console.log(Cat.categories)
interface Redio {
switchRedio(trigger: boolean):void;
}
interface Battery {
checkBatteryStatus(): void;
}
interface RedioWithBattery extends Redio { // 接口继承接口
checkBatteryStatus(): void;
}
class car implements Redio {
switchRedio(trigger: boolean) {
...
}
}
class cellPhone implements RedioWithBattery {
switchRedio(trigger: boolean) {
...
}
checkBatteryStatus() {
...
}
}
enum Direction { // 如果在enum前面加上 const 则为常量枚举
up = 10, // 值默认从 0 开始, 此处赋值后从 10 开始增加
down,
left,
right
}
console.log(Direction.up) // 值为 10
enum Direction2 {
str1 = 'STR1',
str2 = 'STR2'
}
const value = 'STR1'
if (value === Direction2.str1) {
console.log('go str1')
}
function echo<T>(arg: T): T {
return arg
}
const result = echo(true) // 只有当参数传递时才能确定类型,传入什么类型返回什么类型
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]]
}
const result2 = swap(['string', 123])
约束泛型
由于使用泛型时不确定参数的类型,所以不能直接使用传入参数类型的方法和属性,使用时继承需要用到的接口的方法和属性即可使用。
interface IWithLength {
length: number
}
function echoWithLength<T extends IWithLength> (arg: T): T {
console.log(arg.length)
return arg
}
const str = echoWithLength('str')
const obj = echoWithLength({length: 10, width: 20})
const arr = echoWithLength([1, 2, 3])
泛型在类中的使用
class Queue<T> {
private data = []
push (item: T) {
return this.data.push(item)
}
pop () {
return this.data.shift()
}
}
const queue = new Queue<number>()
queue.push(123)
console.log(queue.pop().toFixed())
泛型在接口中的使用
interface KeyPair<T, U> {
key: T,
value: U
}
let kp1: KeyPair<string, number> = {key: 'string', value: 20}
let kp2: KeyPair<number, string> = {key: 10, value: 'str'}
// 定义 number 类型的数组的两种方法
let arr1: number[] = [1, 2, 3]
let arr2: Array<number> = [1, 2, 3]
// 类型别名
type plusType = (x: number, y: number) => number
let sum: plusType
const result1 = sum(1, 2)
type numOrStr = number | string
let result2: numOrStr = 'str'
result2 = 123
// 字面量
const str: 'name' = 'name'
const number: 1 = 1
type Directions = 'up' | 'down' | 'left' | 'right'
let toWhere: Directions = 'up'
// 交叉类型
interface IName {
name: string
}
type IPerson = IName & {age: number}
let person: IPerson = {name: 'Axton', age: 20}
在使用一些第三方库的时候,ts 并不知道我们引入的是什么文件,所以会报错
此时需要定义声明文件
// 声明文件一般放到以 .d.ts 结尾的文件中
declare var jQuery: (selector: string) => any;
// 例:使用
jQuery('#foo')
很多第三方库都会有现成的声明文件,我们通过 npm 安装就好