类型推论
如果没有明确的指定类型,那么 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); // 5myFavoriteNumber = 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('')) // errorconst 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) => voidgetById: (id: number) => T}class User {id?: number; //id主键自增name: string; //姓名age: number; //年龄constructor (name, age) {this.name = namethis.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: Tadd: (x: T, y: T) => T}let myGenericNumber = new GenericNumber<number>()myGenericNumber.zeroValue = 0myGenericNumber.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 类型。
