类型推论
如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any
类型而完全不被类型检查:
let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
联合类型
联合类型(Union Types)表示取值可以为多种类型中的一种。
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
联合类型使用 |
分隔每个类型。
这里的 let myFavoriteNumber: string | number
的含义是,允许 myFavoriteNumber
的类型是 string
或者 number
,但是不能是其他类型。
联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length); // 5
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); // 编译时报错
// index.ts(5,30): error TS2339: Property 'length' does not exist on type 'number'.
上例中,第二行的 myFavoriteNumber
被推断成了 string
,访问它的 length
属性不会报错。
而第四行的 myFavoriteNumber
被推断成了 number
,访问它的 length
属性时就报错了。
类型注解
function greeter (person: string) {
return 'Hello, ' + person
}
let user = 'Yee'
console.log(greeter(user))
给 person
函数的参数添加 : string
类型注解
接口
TypeScript 的核心原则之一是对值所具有的结构进行类型检查。我们使用接口(Interfaces)来定义对象的类型。接口是对象的状态(属性)和行为(方法)的抽象(描述)
interface Persion {
// 只读
readonly id: number;
name: string;
age: number;
// 卡哇伊没有 sex 属性
sex?: string;
};
const person: Persion = {
id: 1,
name: "ade kang",
age: 18,
};
console.log(person);
定义的变量比接口少了一些属性是不允许的,当然多一些属性也是不允许的。
只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候:
类的类型
可以通过接口来实现
(() => {
interface IFLY {
fly(): any;
}
class Person implements IFLY {
fly() {
console.log("---");
}
}
const p1 = new Person();
p1.fly();
})();
定义一个接口继承其他接口(接口与接口叫继承 extends)
interface LightableAlarm extends IFLY, Light {
}
一个类可以实现多个接口(类和接口叫实现 implements )
class Car2 implements Alarm, Light {
alert() {
console.log('Car alert');
}
lightOn() {
console.log('Car light on');
}
lightOff() {
console.log('Car light off');
}
}
函数
泛型
指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。先将位置占这,然后再使用的时候再给定相关类型
function createArray2 <T> (value: T, count: number) {
const arr: Array<T> = []
for (let index = 0; index < count; index++) {
arr.push(value)
}
return arr
}
const arr3 = createArray2<number>(11, 3)
console.log(arr3[0].toFixed())
// console.log(arr3[0].split('')) // error
const arr4 = createArray2<string>('aa', 3)
console.log(arr4[0].split(''))
// console.log(arr4[0].toFixed()) // error
多个泛型参数的函数
function swap <K, V> (a: K, b: V): [K, V] {
return [a, b]
}
const result = swap<string, number>('abc', 123)
console.log(result[0].length, result[1].toFixed())
泛型接口
在定义接口时, 为接口中的属性或方法定义泛型类型
在使用接口时, 再指定具体的泛型类型
interface IbaseCRUD <T> {
data: T[]
add: (t: T) => void
getById: (id: number) => T
}
class User {
id?: number; //id主键自增
name: string; //姓名
age: number; //年龄
constructor (name, age) {
this.name = name
this.age = age
}
}
class UserCRUD implements IbaseCRUD <User> {
data: User[] = []
add(user: User): void {
user = {...user, id: Date.now()}
this.data.push(user)
console.log('保存user', user.id)
}
getById(id: number): User {
return this.data.find(item => item.id===id)
}
}
const userCRUD = new UserCRUD()
userCRUD.add(new User('tom', 12))
userCRUD.add(new User('tom2', 13))
console.log(userCRUD.data)
泛型类
在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型
class GenericNumber<T> {
zeroValue: T
add: (x: T, y: T) => T
}
let myGenericNumber = new GenericNumber<number>()
myGenericNumber.zeroValue = 0
myGenericNumber.add = function(x, y) {
return x + y
}
let myGenericString = new GenericNumber<string>()
myGenericString.zeroValue = 'abc'
myGenericString.add = function(x, y) {
return x + y
}
console.log(myGenericString.add(myGenericString.zeroValue, 'test'))
console.log(myGenericNumber.add(myGenericNumber.zeroValue, 12))
内置对象
JavaScript 中有很多内置对象,它们可以直接在 TypeScript 中当做定义好了的类型。
内置对象是指根据标准在全局作用域(Global)上存在的对象。这里的标准是指 ECMAScript 和其他环境(比如 DOM)的标准。
- ECMAScript 的内置对象
Boolean
Number
String
Date
RegExp
Error
/* 1. ECMAScript 的内置对象 */
let b: Boolean = new Boolean(1)
let n: Number = new Number(true)
let s: String = new String('abc')
let d: Date = new Date()
let r: RegExp = /^1/
let e: Error = new Error('error message')
b = true
// let bb: boolean = new Boolean(2) // error
- BOM 和 DOM 的内置对象
Window
Document
HTMLElement -> HTML标签
DocumentFragment
Event
NodeList
const div: HTMLElement = document.getElementById('test')
const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
console.dir(event.target)
})
const fragment: DocumentFragment = document.createDocumentFragment()
类型断言
类型断言(Type Assertion)可以用来手动指定一个值的类型。也就是我知道这个了类型。
语法§
值 as 类型
或
<类型>值
在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用前者,即 值 as 类型
。