# 安装命令
npm install typescript -g
# 查看版本
tsc --version
npm install ts-node -g
npm install tslib @types/node -g
ts-node math.ts
var/let/const 标识符: 数据类型 = 赋值;
let message: string = 'Hello World'
var name: string = 'tom'
let age: number = 18
const height: number = 1.88
// string: TypeScript 中的字符串类型
// String: JavaScript 的字符串包装类型
const message: String = 'Hello World'
export {}
// 默认情况想进行赋值时,会将赋值的值的类型,作为前面标识符的类型
// 这个过程称之为类型推到/推断
// foo 没有添加类型注解
let foo = 'foo'
foo = 123 // 类型推断
在开发中,有时候为了方便起见我们并不会在声明每一个变量时都写上对应的数据类型,我们更希望可以通过TypeScript本身的特性帮助我们推断出对应的变量类型
如果我们给message赋值123:
这是因为在一个变量第一次赋值时,会根据后面的赋值内容的类型,来推断出变量的类型:
上面的message就是因为后面赋值的是一个string类型,所以message虽然没有明确的说明,但是依然是一个string类型;
数字类型是我们开发中经常使用的类型,TypeScript和JavaScript一样,不区分整数类型(int)和浮点型(double),统一为number类型。
如果你学习过ES6应该知道,ES6新增了二进制和八进制的表示方法,而TypeScript也是支持二进制、八进制、十六进制的表示:
let num1: number = 100 // 十进制
let num2: number = 0b100 // 二级制
let num3: number = 0o100 // 八进制
let num4: number = 0x100 // 十六进制
console.log(num1, num2, num3, num4) // 100 4 64 256
boolean类型只有两个取值:true和false
let flag: boolean = true
flag = 10 > 30
string类型是字符串类型,可以使用单引号或者双引号表示
同时也支持ES6的模板字符串来拼接变量和字符串
let message1: string = 'hello world'
let message2:string = "Hello World"
const name = 'why'
const age = 18
const height = 1.88
let message3 = `name:${name} age:${age} height:${height}`
console.log(message3)
数组类型的定义也非常简单,有两种方式
如果添加其他类型到数组中,那么会报错
// 确定一个事实:names 是一个数组类型,但是数组中存放的是是什么类型的元素呢
// 不好的习惯:一个数组在TypeScript开发中,最好存放的数据类型是固定的(string)
// 类型注解:type annotation
const names1: Array<string> = [] // 不推荐(react jsx 中有冲突)
const names2: string[] = [] // 推荐
// 在数组中存放不同的类型是不好的习惯
// names.push('abc')
// names.push(123) // 报错
const info: object = {
name: 'why',
age: 18
}
info['name'] = 'coderwhy'
console.log(info['age'])
object对象类型可以用于描述一个对象
但是从myinfo中我们不能获取数据,也不能设置数据
在ES5中,如果我们是不可以在对象中添加相同的属性名称的,比如下面的做法
const info = {
title: '程序员',
title: '老师' // 报错
}
通常我们的做法是定义两个不同的属性名字:比如title1和title2
但是我们也可以通过symbol来定义相同的名称,因为Symbol函数返回的是不同的值
const title1 = Symbol('title1')
const title2 = Symbol('title2')
const info = {
[title1]: '程序员',
[title2]: '老师'
}
const n1: null = null
const n2: undefined = undefined
在 JavaScript 中,undefined 和 null 是两个基本数据类型。
在TypeScript中,它们各自的类型也是undefined和null,也就意味着它们既是实际的值,也是自己的类型
在某些情况下,我们确实无法确定一个变量的类型,并且可能它会发生一些变化,这个时候我们可以使用any类型(类似于Dart语言中的dynamic类型)。
any类型有点像一种讨巧的TypeScript手段:
我们可以对any类型的变量进行任何的操作,包括获取不存在的属性、方法
我们给一个any类型的变量赋值任何的值,比如数字、字符串的值;
如果对于某些情况的处理过于繁琐不希望添加规定的类型注解,或者在引入一些第三方库时,缺失了类型注解,这个时候我们可以使用any
包括在Vue源码中,也会使用到any来进行某些类型的适配
// 当进行一些类型断言 as any
// 在不想给某些 javascript 添加具体的数据类型时(原生的Javascript代码是一样)
let message: any = 'Hello World'
message = 123
message = true
message = {}
function foo(payload: any) {}
console.log(message)
unknown是TypeScript中比较特殊的一种类型,它用于描述类型不确定的变量。
function foo() {
return 'abc'
}
function bar() {
return 123
}
// unknow 类型只能复制给 any 和 unknow 类型
// any 类型可以赋值给任意类型
const flag = true
let result: unknown
if (flag) {
result = foo()
} else {
result = bar()
}
console.log(result)
function sum(num1: number, num2: number): void {
console.log(num1 + num2)
}
sum(20, 30)
never 表示永远不会发生值的类型,比如一个函数:
function foo(): never {
// 死循环
while (true) {}
}
function bar(): never {
throw new Error()
}
// 知乎:never 到底应用在什么场景?
function handleMessage(message: string | number | boolean) {
switch (typeof message) {
case 'string':
console.log('string处理方式处理message')
break
case 'number':
console.log('number处理方式处理message')
break
case 'boolean':
console.log('boolean处理方式处理boolean')
break
default:
const check: never = message // 报错
}
}
handleMessage('abc')
handleMessage(123)
// 张三
handleMessage(true)
tuple是元组类型,很多语言中也有这种数据类型,比如Python、Swift等。
// tuple 元组:多种元素的组合
// ‘why’ 18 1.88
// 1.素组的弊端
// const info: any[] = ['why', 18, 1.88]
// const name = info[0]
// console.log(name.length)
// 冗余
// const infoObj = {
// name: 'why',
// age: 18,
// height: 1.88
// }
// 2. 元组的特点
const info: [string, number, number] = ['why', 18, 1.88]
const name = info[0]
console.log(name.length)
const age = info[1]
console.log(age.length) // 报错
// hook: useState
// const [counter, setCounter] = useState(10)
function useState<T>(state: T) {
// T 泛型
let currentState = state
const changeState = (newState: T) => {
currentState = newState
}
// const arr: any[] = [currentState, changeState]
// return arr
const tupple: [T, (newState: T) => void] = [currentState, changeState]
return tupple
}
const [
counter, // number
setCounter // (newState: number) => void
] = useState(10)
setCounter(1000)
const [
title, // string
setTitle // (newState: string) => void
] = useState('abc')
const [
flag, // boolean
setFlag // (newState: boolean) => void
] = useState(true)
// 给参数加上类型注解:num1: number, num2: number
// 给返回值加上注解:():number
// 在开发中,通常情况下可以不写返回值的类型(自动推导)
function sum(num1: number, num2: number) {
return num1 + num2
}
sum(10, 20)
我们也可以添加返回值的类型注解,这个注解出现在函数列表的后面
和变量的类型注解一样,我们通常情况下不需要返回类型注解,因为TypeScript会根据 return 返回值推断函数的返回类型:
某些第三方库处于方便理解,会明确指定返回类型,但是这个看个人喜好;
// 通常情况下,再定义一个函数时,都会给参数加上类型注解的
function foo(message: string) {}
const names = ['abc', 'cba', 'nba']
// 根据上下文环境推导出来的,这个时候可以不添加类型注解
// 上下文中的函数,可以不添加类型注解
names.forEach(function (item) {
console.log(item.split(''))
})
// Point: x/y -> 对象类型
// function printPoint(point:{x:number, y:number}) {
function printPoint(point: { x: number; y: number }) {
console.log(point.x)
console.log(point.y)
}
// printPoint('123') //报错
// printPoint({ x: '123', y: '123' }) // 报错
printPoint({ x: 123, y: 321 })
// Point: x/y/z -> 对象类型
// {x:number, y:number, z?:number}
function printPoint(point: { x: number; y: number; z?: number }) {
console.log(point.x)
console.log(point.y)
console.log(point.z)
}
printPoint({ x: 123, y: 321 }) // 123 321 undefined
printPoint({ x: 123, y: 321, z: 111 }) // // 123 321 111
// number | string 联合类型
function printID(id: number | string) {
// 使用联合类型时,需要特别小型
// narrow: 缩小
if (typeof id === 'string') {
// TypeScript 帮助确定 id 一定是 string 类型
console.log(id.toUpperCase())
} else {
console.log(id)
}
}
printID(123)
printID('abc')
// 让一个参数本身是可选的
// 一个参数是一个可选类型的时候,它类似于是这个参数是 类型|undefined 的联合类型
// function foo(message?: string) {
// console.log(message)
// }
function foo(message: string | undefined) {
console.log(message)
}
// foo()
foo(undefined)
foo('123')
// type 用于定义类型别名 (type alias)
type IDType = string | number | boolean
type PointType = {
x: number
y: number
z?: number
}
function printId(id: IDType) {}
function printPoint(point: PointType) {}
//
// const el: HTMLElement = document.getElementById('why')
// 1.类型断言
const el = document.getElementById('why') as HTMLImageElement
el.src = 'url地址'
// el.classList
// 2.另外案例:Person是Student的父类
class Person {}
class Student extends Person {
studying() {}
}
function sayHello(p: Person) {
;(p as Student).studying()
}
const stu = new Student()
sayHello(stu)
// 3. 了解:as any/unkown 不推荐
const message = 'Hello World'
const num1: number = message as any as number
const num2: number = message as unknown as number
// message? -> undefined | string
function pringMessage(message?: string) {
// if (message) {
// console.log(message.length)
// }
// vue3 源码 proxy!
console.log(message!.length)
}
pringMessage('Hello World')
pringMessage('哈哈哈哈哈')
pringMessage()
type Person = {
name: string
friend?: {
name: string
age?: number
girlFriend?: {
name: string
age?: number
}
}
}
const info: Person = {
name: 'why'
// friend: {
// name: 'kobe'
// }
}
// 另外一个文件中
console.log(info.name)
// console.log(info.friend!.name)
// if (info.friend) {
// console.log(info.friend.name)
// }
console.log(info.friend?.name) // 可选链
console.log(info.friend?.age)
console.log(info.friend?.girlFriend?.name)
// why
// undefined
// undefined
// undefined
!!操作符:
const message = 'Hello World'
// const flag = Boolean(message)
// console.log(flag)
const flag = !!message
console.log(flag)
??操作符:
// let message: string|null = null
let message: string | null = 'Hello World'
// const content = message ? message : '你好啊,李银河'
const content = message ?? '你好啊,李银河'
console.log(content)
// "Hello World" 也是可以作为类型的,叫做字面量类型
const message: 'Hello World' = 'Hello World'
let num: 123 = 123
// num = 321 // 不可以,字面量类型的类型和值必须一致
// 字面量类型的意义,就是必须结合联合类型
type Alignment = 'left' | 'right' | 'center'
let align: Alignment = 'left'
align = 'left'
align = 'right'
align = 'right'
// align = 'hhhh' // 报错
// const info = {
// name: 'why',
// age: 18
// }
// info.name = 'kobe'
type Method = 'GET' | 'POST'
type Request = {
url: string
method: Method
}
function request(url: string, method: Method) {}
// const options: Request = {
// url: 'http://www.coderwhy.org/abc',
// method: 'POST' // 类型推导,推导出来 options.method 是 string 类型
// }
// options.method = '123' // 安全隐患
// request(options.url, options.method) // 第二个参数报错
// const options = {
// url: 'http://www.coderwhy.org/abc',
// method: 'POST' // 类型推导,推导出来 options.method 是 string 类型
// }
// request(options.url, options.method as Method) // 使用类型断言
const options = {
url: 'http://www.coderwhy.org/abc',
method: 'POST' // 类型推导,推导出来 options.method 是 string 类型
} as const
request(options.url, options.method)
什么是类型缩小呢?
// 1. typeof 的类型缩小
type IDType = number | string
function printID(id: IDType) {
if (typeof id === 'string') {
console.log(id.toUpperCase())
} else {
console.log(id)
}
}
// 2. 平等的类型缩小 (=== == !== !=/switch)
type Direction = 'left' | 'right' | 'top' | 'bottom'
function printDirection(direction: Direction) {
// 1. if 判断
// if (direction === 'left') {
// console.log(direction)
// } else if() {}
// 2. switch 判断
// switch(direction) {
// case 'left':
// console.log(direction);
// break
// case ...
// }
}
// 3. instanceof
function printTime(time: string | Date) {
if (time instanceof Date) {
console.log(time.toUTCString())
} else {
console.log(time)
}
}
class Student {
studying() {}
}
class Teacher {
teaching() {}
}
function work(p: Student | Teacher) {
if (p instanceof Student) {
p.studying()
} else {
p.teaching()
}
}
// 4. in
type Fish = {
swimming: () => void
}
type Dog = {
running: () => void
}
function walk(animal: Fish | Dog) {
if ('swimming' in animal) {
animal.swimming()
} else {
animal.running()
}
}
const fish = {
swimming() {
console.log('swimming')
}
}
function calc(
n1: number,
n2: number,
fn: (num1: number, num2: number) => number
) {
return fn(n1, n2)
}
const result1 = calc(20, 30, function (a1, a2) {
return a1 + a2
})
console.log(result1) // 50
const result2 = calc(20, 30, function (a1, a2) {
return a1 * a2
})
console.log(result2) // 600
// 1. 函数作为参数时,在参数中如何编写类型
function foo() {}
type FooFnType = () => void
function bar(fn: FooFnType) {
fn()
}
bar(foo)
// 2. 定义常量时,编写函数的类型
type AddFnType = (num1: number, num2: number) => number
const add: AddFnType = (a1: number, a2: number) => {
return a1 + a2
}
// 可选类型必须写在必须按类型的后面的
// y -> undefined | number
function foo(x: number, y?: number) {
console.log(x, y)
}
foo(20, 30)
foo(20)
// 必传参数 -> 有默认值的参数 -> 可选参数
function foo(x: number, y: number = 100) {
console.log(x, y)
}
foo(20) // 20 100
function sum(initalNum: number, ...nums: number[]) {
let total = initalNum
for (const num of nums) {
total += num
}
return total
}
console.log(sum(20, 30))
console.log(sum(20, 30, 40))
console.log(sum(20, 30, 40, 50))
// this 是可以被推导出来的 info对象(typeScript 推导出来)
const info = {
name: 'why',
eating() {
console.log(this.name + ' eating')
}
}
info.eating()
但是对于某些情况来说,我们并不知道this到底是什么?
这段代码运行会报错的:
这个时候,通常TypeScript会要求我们明确的指定this的类型
type ThisType = { name: string }
function eating(this: ThisType, message: string) {
console.log(this.name + ' eating', message)
}
const info = {
name: 'why',
eating
}
// 隐式绑定
info.eating('哈哈哈')
// 显式绑定
eating.call({ name: 'kobe' }, '呵呵呵')
eating.apply({ name: 'james' }, '嘿嘿嘿 ')
type AddType = number | string
function add(a1: AddType, a2: AddType) {
return a1 + a2
}
/**
* 通过联合类型有2个缺点:
* 1. 进行很多的逻辑判断(类型缩小)
* 2. 返回值的类型依然不能确定
*/
function add(a1: number | string, a2: number | string) {
if (typeof a1 === 'number' && typeof a2 === 'number') {
return a1 + a2
} else if (typeof a1 === 'string' && typeof a2 === 'string') {
return a1 + a2
}
}
// 函数的重载:函数的名称相同,但是参数不同的几个函数,就是函数的重载
function sum(num1: number, num2: number): number
function sum(num1: string, num2: string): string
function sum(num1: any, num2: any): any {
return num1 + num2
}
const result2 = sum('abc', 'cba')
console.log(result, result2) // 50
sum({name:'why'}, {age:18}) // 报错
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
eating() {
console.log(this.name + ' eating')
}
}
const p = new Person('why', 18)
console.log(p.name)
console.log(p.age)
p.eating()
/*
why
18
why eating
*/
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
eating() {
console.log('eating')
}
}
class Student extends Person {
sno: number
constructor(name: string, age: number, sno: number) {
// 调用父类的构造器
super(name, age)
this.sno = sno
}
// overwrite 重写
eating() {
super.eating()
console.log('student eating')
}
studying() {
console.log('studying')
}
}
class Teacher extends Person {
title: string = ''
teaching() {
console.log('teaching')
}
}
const stu = new Student('why', 12, 111)
stu.name = 'coderwhy'
stu.age = 10
console.log(stu.name)
console.log(stu.age)
stu.eating()
/*
coderwhy
10
eating
student eating
*/
class Animal {
action() {
console.log('animal running')
}
}
class Dog extends Animal {
action() {
console.log('dog running!!!')
}
}
class Fish extends Animal {
action() {
console.log('fish swimming!!!')
}
}
class Bird extends Animal {
action() {
console.log('bird flying!!!')
}
}
function makeActions(animals: Animal[]) {
animals.forEach((animal) => animal.action())
}
makeActions([new Dog(), new Fish(), new Bird()])
/*
dog running!!!
fish swimming!!!
bird flying!!!
*/
// 只能在类内部访问
class Person {
private name: string = ''
// 封装了2个方法,通过方法来访问name
getName() {
return this.name
}
setName(newName) {
this.name = newName
}
}
const p = new Person()
p.setName('why')
console.log(p.getName())
// protected: 在类的内部和子类中可以访问
class Person {
protected name: string = '123'
}
class Student extends Person {
getName() {
return this.name
}
}
const stu = new Student()
console.log(stu.getName())
class Person {
// readonly name: string = '123'
// 1. 只读属性可以在构造器中赋值, 赋值之后就不可以修改
// 2. 属性本身不能进行修改,但是如果它是对象类型,对象中的属性是可以修改
readonly name: string
readonly friend?: Person
age?: number
constructor(name: string, friend?: Person) {
this.name = name
this.friend = friend
}
}
const p = new Person('why', new Person('kobe'))
console.log(p.name)
console.log(p.friend)
// p.name = '123' // 报错
// p.friend = new Person('james') // 报错
if (p.friend) {
p.friend.age = 30 // 可以修改
}
class Person {
private _name: string // 定义私有属性时,习惯以下划线开头
constructor(name: string) {
this._name = name
}
// 访问权 getter setter
set name(newName) {
this._name = newName
}
get name() {
return this._name
}
}
const p = new Person('why')
console.log(p.name)
p.name = '123'
console.log(p.name)
/*
why
123
*/
class Person {
private _name: string // 定义私有属性时,习惯以下划线开头
constructor(name: string) {
this._name = name
}
// 访问权 getter setter
set name(newName) {
this._name = newName
}
get name() {
return this._name
}
}
const p = new Person('why')
console.log(p.name)
p.name = '123'
console.log(p.name)
/*
why
123
*/
function makeArea(shape: Shape) {
return shape.getArea()
}
abstract class Shape {
abstract getArea()
}
class Rectangle extends Shape {
private width: number
private height: number
constructor(width: number, height: number) {
super()
this.width = width
this.height = height
}
getArea() {
return this.width * this.height
}
}
class Circle extends Shape {
private r: number
constructor(r: number) {
super()
this.r = r
}
getArea() {
return this.r * this.r * 3.14
}
}
const rectangle = new Rectangle(20, 30)
console.log(makeArea(rectangle))
const circle = new Circle(10)
console.log(makeArea(circle))
// makeArea(三角形)
// makeArea(矩形)
// makeArea(圆形)
// 缺点
// makeArea(123)
// makeArea(undefined)
// makeArea('123')
class Person {
name: string = '123'
eating() {}
}
const p = new Person()
const p1: Person = {
name: 'why',
eating() {}
}
function printPerson(p: Person) {
console.log(p.name)
}
printPerson(new Person())
printPerson({ name: 'kobe', eating() {} })
// 通过类型别名(type)来声明对象类型
// type InfoType = { name: string; age: number }
//另外一种方式声明对象类型:接口 interface
interface InfoType {
name: string
age: number
}
const info: InfoType = {
name: 'why',
age: 18
}
// 通过类型别名(type)来声明对象类型
// type InfoType = { name: string; age: number }
//另外一种方式声明对象类型:接口 interface
// 在其中可以定义可选类型
interface InfoType {
name: string
age: number
friend?: {
name: string
}
}
const info: InfoType = {
name: 'why',
age: 18,
friend: {
name: 'kobe'
}
}
console.log(info.friend?.name)
// 通过类型别名(type)来声明对象类型
// type InfoType = { name: string; age: number }
//另外一种方式声明对象类型:接口 interface
// 在其中可以定义可选类型
// 也可以定义只读属性
interface InfoType {
readonly name: string
age: number
friend?: {
name: string
}
}
const info: InfoType = {
name: 'why',
age: 18,
friend: {
name: 'kobe'
}
}
console.log(info.friend?.name)
console.log(info.name)
// info.name = '123'
// 通过 interface 定义索引类型
interface IndexLanguage {
[index: number]: string
}
const frontLanguage: IndexLanguage = {
0: 'HTML',
1: 'CSS',
2: 'JavaScript',
3: 'Vue'
}
interface LanguageYeaar {
[name: string]: number
}
const languageYear: LanguageYeaar = {
C: 1972,
Java: 1995,
JavaScript: 1996,
TypeScript: 2014
}
// type CalcFn = (n1: number, n2: number) => number
// 可调用接口
interface CalcFn {
(n1: number, n2: number): number
}
function calc(num1: number, num2: number, calcFunc: CalcFn) {
return calcFunc(num1, num2)
}
const add: CalcFn = (num1, num2) => num1 + num2
calc(20, 30, add)
interface ISwim {
swimming: () => void
}
interface IFly {
flying: () => void
}
interface IAction extends ISwim, IFly {}
const action: IAction = {
swimming() {},
flying() {}
}
// 一种组合类型的方式:联合类型
type WhyType = number | string
type Direction = 'left' | 'right' | 'center'
// 另一种组合类型的方式:交叉类型
// type WType = number & string // never 没有意义
interface ISwim {
swimming: () => void
}
interface IFly {
flying: () => void
}
type MyType1 = ISwim | IFly
type MyType2 = ISwim & IFly
const obj1: MyType1 = {
swimming() {}
}
const obj2: MyType2 = {
swimming() {},
flying() {}
}
interface ISwim {
swimming: () => void
}
const a: ISwim = {
swimming() {}
}
function foo(swim: ISwim) {}
interface IEat {
eating: () => void
}
// 类实现接口
class Animal {}
// 继承:只能实现单继承
// 实现:实现接口,类可以实现多个接口
class Fish extends Animal implements ISwim, IEat {
swimming() {
console.log('Fish Swimmig')
}
eating() {
console.log('Fish Eating')
}
}
class Person implements ISwim {
swimming() {
console.log('Fish Swimmig')
}
}
// 编写一些公关的API:面向接口编程
function swimAction(swimable: ISwim) {
swimable.swimming()
}
// 1. 所有实现了接口的类对应的对象,都是可以传入
swimAction(new Fish())
swimAction({ swimming() {} })
swimAction(new Person())
interface IFoo {
name: string
}
interface IFoo {
age: number
}
const foo: IFoo = {
// 合并
name: 'why',
age: 18
}
// document.getElementById('app') as HTMLDivElement
// window.addEventListener
interface Window {
age: number
}
window.age = 19
console.log(window.age)
// 报错
// type IBar = {
// name: string
// }
// type IBar = {
// age: number
// }
interface IPerson {
name: string
age: number
height: number
}
const p: IPerson = {
name: 'why',
age: 18,
height: 1.88
// address: '广州市' // 报错
}
const info = {
name: 'why',
age: 18,
height: 1.88,
address: '广州市'
}
// freshness 擦除
const p2: IPerson = info // 不报错
console.log(info)
console.log(p2)
enum Direction {
LEFT,
RIGHT,
TOP,
BOTTOM
}
function turnDirection(direction: Direction) {
switch (direction) {
case Direction.LEFT:
console.log('改变角色的方向向左')
break
case Direction.RIGHT:
console.log('改变角色的方向向右')
break
case Direction.TOP:
console.log('改变角色的方向向上')
break
case Direction.BOTTOM:
console.log('改变角色的方向向下')
break
default:
const foo: never = direction
break
}
}
turnDirection(Direction.LEFT)
turnDirection(Direction.RIGHT)
turnDirection(Direction.TOP)
turnDirection(Direction.BOTTOM)
// enum Direction {
// LEFT = 100,
// RIGHT, //101
// TOP, // 102
// BOTTOM // 103
// }
enum Direction {
LEFT = "LEFT",
RIGHT= "RIGHT",
TOP= "TOP",
BOTTOM= "BOTTOM"
}
function turnDirection(direction: Direction) {
switch (direction) {
case Direction.LEFT:
console.log('改变角色的方向向左')
break
case Direction.RIGHT:
console.log('改变角色的方向向右')
break
case Direction.TOP:
console.log('改变角色的方向向上')
break
case Direction.BOTTOM:
console.log('改变角色的方向向下')
break
default:
const foo: never = direction
break
}
}
turnDirection(Direction.LEFT)
turnDirection(Direction.RIGHT)
turnDirection(Direction.TOP)
turnDirection(Direction.BOTTOM)
function foo(arg: number): number {
return arg
}
function foo(arg: any): any {
return arg
}
// 类型的参数化
// 在定义函数时,不决定参数的类型
// 而是让调用者以参数的形式告知,我这里函数的餐宿应该是什么类型
function sum<Type>(num: Type): Type {
return num
}
// 1. 调用方式一:明确的传入了类型
sum<number>(20)
sum<{ name: string }>({ name: 'why' })
sum<any[]>(['abc'])
// 2. 调用方式二:类型推导
sum(50)
sum('abc')
function foo<T, E, O>(arg1: T, arg2: E, arg3: O) {}
foo<number, string, boolean>(10, 'abc', true)
interface IPerson<T1 = string, T2 = number> {
name: T1
age: T2
}
// const p: IPerson = {
// name: 'why',
// age: 18
// }
const p: IPerson = {
name: 'why',
age: 18
}
class Point<T> {
x: T
y: T
z: T
constructor(x: T, y: T, z: T) {
this.x = x
this.y = y
this.z = z
}
}
const p1 = new Point('1.33.2', '2.22.3', '4.22.1')
const p2 = new Point<string>('1.33.2', '2.22.3', '4.22.1')
const p3: Point<string> = new Point('1.33.2', '2.22.3', '4.22.1')
const names1: string[] = ['abc', 'cba', 'nba']
const names2: Array<string> = ['abc', 'cba', 'nba'] // 不推荐(react jsx <>)
// function getLength(arg:string|any[]) {
// return arg.length
// }
interface ILength {
length: number
}
function getLength<T extends ILength>(arg: T) {
return arg.length
}
// getLength(123) // 报错
getLength('abc')
getLength(['abc', 'cba'])
getLength({ length: 100 })
export function sum(num1: number, num2: number) {
return num1 + num2
}
export function sub(num1: number, num2: number) {
return num1 - num2
}
export namespace time {
export function format(time: string) {
return '2222-02-22'
}
export function foo() {}
export let name: string = 'abc'
}
export namespace price {
export function format(price: number) {
return '99.99'
}
}
// 使用
time.format
time.foo
time.name
price.format
import { sum, sub } from './utils/math'
import { time, price } from './utils/format'
console.log(sum(20, 30))
console.log(sub(20, 30))
console.log(time.format('1111'))
console.log(price.format(123))
const imageEl = document.getElementById("image") as HTMLImageElement
// 声明变量/函数/类
declare let whyName: string
declare let whyAge: number
declare let whyHeight: number
declare function whyFoo(): viod
declare class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
declare module 'lodash' {
export function join(arr: any[]): void
}
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.png'
declare module '*.svg'
declare module '*.gif'
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent
export component
}
declare namespace $ {
export function ajax(setting: any): any
}
$.ajax({
url: 'hrrp://123.207.32.32:8000/home/multidata',
success(res: any) {
console.log(res)
}
})