基础知识
基础类型: number string boolean array object undefined void
1. enum 枚举的使用
2. type 和 interface 区别
3. 联合类型 | 类似或
的概念
如果 type D = A | B | C
- D 必须含有 A B C 中一个的所有成员
- D 的其他成员必须是 A B C 中的成员
type A = {
a: number,
b: number,
c: number
}
type B = {
a: number,
d: number,
e: number
}
type C = {
a: number,
f: number,
g: number
}
type D = A | B | C
const sth: D = {
a: 1,
b: 1,
c: 1,
d: 1,
g: 1,
// h: 1
}
4. 交叉类型 & 类似与
的概念
5. typeof 可以基于已有的变量/函数获得他的类型
function toArray(x: number): Array<number> {
return [x]
}
type Func = typeof toArray
6. keyof 获取一个对象当中的 key
interface Person {
name: number,
age: number
}
type XX = keyof Person // 'name' | 'age'
const x: XX = 'age'
7. in 遍历枚举类型
type Keys = "a" | "b" | 'c'
type Obj = {
[key in Keys]: number
}
const obj: Obj = {
a: 1,
b: 1,
c: 1,
// d: 1
}
8. extends
泛型:对于类型的参数
interface A<T> {
a: T
}
const b: A<number> = {
a: 1
}
extends 用来约束泛型的类型
interface ILengthwise {
length: number
}
function log<T extends ILengthwise> (arg: T): T {
return arg
}
log({length: 1, width: 1})
9. Partial
将类型成员都变为可选
interface XX {
name: string,
sex: string
}
type AA = Partial<XX>
/**
* {
* name?: string,
* sex?: string
* }
*/
10. Required
将类型成员都变为必选
面试题及实战
- 你觉得 ts 的好处是什么?
1.1 TypeScript是 JavaScript 的加强版,它给 JavaScript 添加了可选的静态类型和基于类的面向对象编程,它拓展了 JavaScript 的语法。
1.2 TypeScript 是纯面向对象的编程语言,包含类和接口的概念。
1.3 TS 在开发时就能给出编译错误,而 JS 错误则需要在运行时才能暴露
1.4 作为强类型的语言,可以明确知道数据的类型。代码可读性极强,方便多人协作。
1.5 TS 中有很多方便的特性,如可选链。
- type 和 interface 的区别
重点:type 用来描述类型,interface 用来描述接口
2.1 都可以描述一个对象或函数
interface User {
name: string
age: string
}
interface SetUser {
(name: string, sex: string): void
}
type User {
name: string,
age: string
}
type SetUser = (name: string, age: string) => void
2.2 都允许拓展
interface 和 type 都可以拓展,而且两者可以相互拓展。效果差不多,但是两者语法不同
// interface extends interface
interface Name {
name: string
}
interface User extends Name {
age: number
}
// type extends type
type Name = {
name: string
}
type User = Name & { age: number }
// interface extends type
type Name = {
name: string
}
interface User extends Name {
age: number
}
// type extends interface
interface Name {
name: string
}
type User = Name & {
age: number
}
2.3 只有 type 能做的
type 可以声明基本类型别名,联合类型,元组等类型
// 基本类型别名
type Name = string
// 联合类型
interface Dog {
wong()
}
interface Cat {
miao()
}
type Pet = Dog | Cat
// 具体定义数组每个位置的类型
type PetList = [Dog, Cat]
// 获取一个 js 变量的类型时,使用 typeof
const div = document.createElement('div')
type D = typeof div
- 如何基于一个已有的类型,扩展出一个大部分内容相似,但是有部分区别的类型?
首先可以通过 Pick 和 Omit
interface User {
name: string,
sex: string,
age: number
}
type BB = Pick<User, 'name' | 'age'>
其次可以通过 Partial、Required
再者可以通过泛型。
- 写一个 routerHelper
import { Dictionary } from 'vue-router/types/router';
import Router, { RoutePath } from '../router'
type BaseRouteParam = Dictionary<string>
export interface IndexParam extends BaseRouteParam {
index: string
}
export interface AboutParam extends BaseRouteParam {
about: string
}
export interface UserParam extends BaseRouteParam {
user: string
}
export interface ParamMap {
[RoutePath.Index]: IndexParam,
[RoutePath.About]: AboutParam,
[RoutePath.User]: UserParam,
}
class RouterHelper {
static push<T extends RoutePath> (path: T, query: ParamMap[T]) {
return Router.push({
path, query
})
}
}
export default RouterHelper
- 写一个 CountDown
import { EventEmitter } from 'eventemitter3'
enum CountDownStatus {
running,
stoped
}
export enum CountDownEventName {
START = 'start',
RUNNING = 'running',
STOP = 'stop'
}
type CountDownEventMap = {
[CountDownEventName.START]: [],
[CountDownEventName.STOP]: [],
[CountDownEventName.RUNNING]: [RemainTimeData, number],
}
interface RemainTimeData {
hours: number,
minutes: number,
seconds: number,
counts: number
}
export default class CountDown extends EventEmitter<CountDownEventMap> {
private static COUNT_TICKS = 10
private static SECOND_TICKS = 100 * CountDown.COUNT_TICKS
private static MINITE_TICKS = 60 * CountDown.SECOND_TICKS
private static HOUR_TICKS = 60 * CountDown.MINITE_TICKS
private status: CountDownStatus = CountDownStatus.stoped
private remainTime = 0
private endTime = 0
private step = 100
private timer = 0
constructor(endTime: number, step: number) {
super()
this.endTime = endTime
this.step = step
this.start()
}
public start() {
if (this.status === CountDownStatus.stoped) {
this.status = CountDownStatus.running
this.emit(CountDownEventName.START)
this.countdown()
}
}
public stop() {
if (this.status === CountDownStatus.running) {
this.status = CountDownStatus.stoped
this.emit(CountDownEventName.STOP)
clearTimeout(this.timer)
}
}
private countdown() {
this.emit(CountDownEventName.RUNNING, this.parseRemainTime(), this.remainTime)
this.timer = requestAnimationFrame(() => {
this.remainTime = Math.max(this.endTime - Date.now(), 0)
if (this.remainTime > 0) {
this.countdown()
} else {
this.stop()
}
});
}
private parseRemainTime() {
let time = this.remainTime
const hours = Math.floor(time / CountDown.HOUR_TICKS)
time = time % CountDown.HOUR_TICKS
const minutes = Math.floor(time / CountDown.MINITE_TICKS)
time = time % CountDown.MINITE_TICKS
const seconds = Math.floor(time / CountDown.SECOND_TICKS)
time = time % CountDown.SECOND_TICKS
const counts = Math.round(time / CountDown.COUNT_TICKS)
return {
hours, minutes, seconds, counts
}
}
}
- tsc 原理
源码 => 扫描器(Scanner)=> Token 流 => 解析器(Parser) => AST =>
- 类型检查
- 生成 js 代码