TypeScript
Typescript是一个JavaScript的超集,即Type+Script,为JS添加类型支持。
Typescript属于静态类型编程语言,JS属于动态类型编程语言
JS类型(执行期做类型检查):需等到代码真正执行才能发现错误(晚)
TS类型(编译期做类型检查):在代码编译时即可发现错误(早)→减少找BUG、改BUG的时间
TS初体验
安装编译TS的工具包
目的:Node.js/浏览器,只认识 JS 代码,不认识 TS 代码;需先将TS代码转为JS代码
typescript 包:实现了 TS -> JS 的转化,用来编译 TS 代码的包
安装命令:
npm i -g typescript
//验证是否安装成功
tsc-v
内在机制:
编译并运行 TS 代码
1.创建 hello.ts 文件
console.log('hello ts');
let age: number = 15
console.log(age);
2.将 TS 编译为 JS:在终端中输入命令,tsc hello.ts→同级目录会出行同名JS文件
console.log('hello ts');
var age = 15;
console.log(age);
3.执行JS代码:node hello.js
简化运行TS步骤
问题:每次修改代码后,需重复执行两个命令→麻烦
简化方式:使用ts-node 包→直接在 Node.js 中执行 TS 代码
安装命令:
npm i -g ts-node
使用方式:
ts-node hello.ts
注意:在内部将TS -> JS,然后,再运行 JS 代码
TypeScript 常用类型
类型注解
//:number 就是类型注解
let age: number = 18
作用:为变量添加约束类型→约定什么类型,就只能给变量赋值该类型
常用类型分类
1.JS 已有类型
- 原始类型:number/string/boolean/null/undefined/symbol。
- 对象类型:object(包括,数组、对象、函数等对象);
2.TS 新增类型
- 联合类型、自定义类型(类型别名)、接口、元组、字面量类型、枚举、void、any 等
原始类型
number/string/boolean/null/undefined/symbol
完全按照 JS 中类型的名称来书写
let age: number = 18
let myName: string = '小张'
let isLoading: boolean = false
let a: null = null
let b: undefined = undefined
let s: symbol = Symbol()
数组类型
// 数字类型
let numbers: number[] = [1,2,3,4]
// let numbers1: Array<number> [1,2,3,4]
// 布尔值类型数组
let b: boolean[] = [true, false]
//联合类型:
//添加小括号, 表示;首先是数组,然后,这个数组中能够出现number或string类型的元素
let arr: (number | string)[] = [1,'a',2,'b',3,'c']
// 不添加小括号,表示:arr1既可以是number类型,又可以是string[]
// let arr1: number | string[] = ['a', 'b']
// let arr1: number | string[] = 123
类型别名(自定义类型)
通过类型别名,简化该类型的使用
// 改造:类型别名
type CustomArray = (number | string)[]
// let arr: (number | string)[] = [1,'a',2,'b',3,'c']
let arr1: CustomArray = [1,'a',2,'b',3,'c']
// let arr1: (number | string)[] = [1,'x',2,'y',3,'z']
let arr2: CustomArray = [1,'x',2,'y',3,'z']
函数类型
函数指定类型的两种方式:
1.单独指定参数、返回值类型
2.同时指定参数、返回值类型
// 1.单独指定参数、返回值类型
// function add(num1: number, num2:number) :number {
// return num1 + num2
// }
// console.log(add(1,2))
// const add1 = (num1:number, num2:number ): number => {
// return num1 + num2
// }
// console.log(add1(2,6));
// 2.同时指定参数、返回值类型
const add: (num1:number, num2:number) => number =(num1, num2) => {
return num1 + num2
}
console.log(add(6,9))
3.函数如果没有返回值,则返回值类型为void
function greet(name: string): void {
console.log('hello', name)
}
greet('lucy')
4.可选参数
// 可选参数可以位于必选参数后面,但比选参数不能位于可选参数后面
function mySlice(start?: number, end?: number): void {
console.log('起始索引:', start, '结束索引:', end);
}
mySlice()
mySlice(1)
mySlice(1,6)
对象类型
JS对象类型由属性和方法构成;
TS对象类型是描述对象的结构
let person: {
name:string
age:number
sayHi(): void
greet(name: string): void
} = {
name:'小张',
age:21,
sayHi() {},
greet(name) {}
}
可选属性:
function myAxios(config: {url: string; method?: string}) {
myAxios({
url: ''
})
}
接口
1.声明interface(接口)后,直接使用接口名称作为变量的类型
// let person: {name:string; age:number; sayHi(): void; greet(name: string): void } = {
// name:'小张',
// age:21,
// sayHi() {},
// greet(name) {}
// }
// let person1: {name:string; age:number; sayHi(): void; greet(name: string): void }
// 接口:
interface IPerson {
name:string
age:number
sayHi(): void
greet(name: string): void
}
let person: IPerson = {
name:'小张',
age:21,
sayHi() {},
greet(name) {}
}
let person1: IPerson = {
name:'小唐',
age:21,
sayHi() {},
greet(name) {}
}
2.interface(接口)和 type(类型别名)的对比:
相同:都可给对象指定类型
不同:接口,只能为对象指定类型;类型别名可为任意类型指定别名
3.接口继承
interface Point2D { x:number; y: number }
// interface Point3D { x:number; y: number; z:number }
// 使用继承 实现复用:
interface Point3D extends Point2D {z:number}
let p3: Point3D = {
x:9,
y:8,
z:10
}
元组(Tuple)
使用场景:确切知道包含多少个元素,以及特点索引对应的类型
// let posiition: number[] = [39,114,55,69]
// 使用元组
// 使用场景:确切地知道包含多少个元素,以及特定索引对应的类型时
let posiition: [number, number] = [39,114]
类型推论
由于类型推论的存在,有些地方,类型注解可省略不写
发生类型推论场景:
1.声明变量并初始化时
2.决定函数返回值时
// 声明变量并立即初始化值,此时,可以省略类型注解
let age = '18'
// age = ''
// 注意:如果声明变量但没有立即初始化值,此时,还必须手动添加类型注解
let a: number
a = 18
// a = ''
// --------------------------------------------
function add (num1:number, num2:number) {
return num1 + num2
}
add(1,2)
//add(false,5)
类型断言
使用as实现类型断言,使alink类型变得更加具体→即可访问到a标签特有属性和方法
// const alink = document.getElementById('link')
// alink.href
// 类型断言
const aLink = document.getElementById('link') as HTMLAnchorElement
aLink.href
技巧:查看对应标签类型的方法:
在浏览器控制台,通过console.dir() 打印 DOM 元素→属性列表最后面,即显示标签元素
字面量类型
// 类型为string
// str是一个变量(let),值可以是任意字符串
let str = 'Hello TS'
// 类型为 'hello TS'
// str2是一个常量,它的值不能变化只能是'hello TS'
const str2 = 'hello TS'
// 字面量类型:用来表示一组明确的可选值列表
// 某个特定的字符串、数字、对象也可以作为 TS 中的类型
const str3:'hello TS' = 'hello TS'
let age:18 = 18
// 一般配合联合类型一起使用
function changeDirection (direction: 'up' | 'down' | 'left' | 'right') {}
changeDirection('left')
枚举
// 枚举
// 默认情况下,枚举成员有值,从0开始自增(数字枚举)
// enum Direction { Up, Down, Left, Right}
// function changeDirection(direction: Direction) {
// console.log(direction)
// }
// changeDirection(Direction.Up)
// 成员设置初始值
enum Direction { Up=2, Down=4, Left=6, Right=8}
function changeDirection(direction: Direction) {
console.log(direction)
}
changeDirection(Direction.Up)
字符串枚举
// 枚举可以是数字类型,也可以是字符串类型
enum Direction { 'Up', 'Down', 'Left', 'Right'}
function changeDirection(direction: Direction) {
console.log(direction)
}
changeDirection(Direction.Up)
枚举的原理说明:枚举不仅作类型,还提供值;会被编译为JS代码
var songs = ['西安', '成都'];
var Direction;
(function (Direction) {
Direction["Up"] = "UP";
Direction["Down"] = "DOWN";
Direction["Left"] = "LEFT";
Direction["Right"] = "RIGHT";
})(Direction || (Direction = {}));
function changeDirection(direction) { }
changeDirection(Direction.Up);
any 类型
不推荐使用any
TypeScript 变为 “AnyScript”→失去 TS 类型保护的优势
typeof
//typeof:用来在 JS 中获取数据的类型
console.log(typeof 'Hello TS') // string
let p = { x: 1, y: 2 }
//可以在类型上下文中引用变量或属性的类型
function formatPoint(point: typeof p) {}
// function formatPoint(point: { x: number; y: number }) {}
formatPoint({ x: 1, y: 100 })
// --
let num: typeof p.x
function add(num1: number, num2: number) {
return num1 + num2
}
//typeof 只能用来查询变量或属性的类型
// typeof 不能查询函数调用的类型
// let ret: typeof add(1, 2)
TypeScript 高级类型
class类
1.不仅提供了class 的语法功能,也作为一种类型存在
class Person {
//实例属性初始化
age: number
gender = '男'
// gender: string = '男'
}
const p = new Person()
p.age
p.gender
2.构造函数
class Person {
//成员初始化后,才可通过this.age、this.gender访问实例成员
age: number
gender: string
//需为构造函数指定类型注解→否则会被隐式推断为any
//构造函数不需要返回值类型
constructor(age: number, gender: string) {
// 实例属性初始化
this.age = age
this.gender = gender
}
}
const p = new Person(18, '男')
console.log(p.age, p.gender)
3.实例方法
class Point {
x = 1
y = 2
scale(n: number) {
this.x *= n
this.y *= n
}
}
const p = new Point()
p.scale(10)
console.log(p.x, p.y)//10,20
4.继承父类
class Animal {
move() {
console.log('走两步')
}
}
// 通过extends实现继承
// 继承之后子类则具备父类所有的属性和方法
class Dog extends Animal {
name = '二哈'
bark() {
console.log('旺旺!')
}
}
const d = new Dog()
d.move()
d.bark()
console.log(d.name)
5.实现接口
interface Singale {
sing(): void
name: string
}
// 通过 implements 关键字让 class 实现接口
class Person implements Singale {
name = 'jack'
sing() {
console.log('你是我的小呀小苹果')
}
}
6.成员可见性-public
// 父类
// public:公有的、公开的;在任何地方都可被访问到
//public 是默认可见性,所以,可以直接省略
class Animal {
public move() {
console.log('走两步')
}
}
const a = new Animal()
a.move()
// 子类
class Dog extends Animal {
bark() {
console.log('旺旺!')
}
}
const d = new Dog()
d.move()
7.成员可见性-protected
// 父类
class Animal {
// 这个方法是受保护的
// 不可在实例对象中访问,只能在类和子类内部通过this进行访问
protected move() {
console.log('走两步')
}
run() {
this.move()
console.log('跑起来')
}
}
const a = new Animal()
// a.move()
// 子类
class Dog extends Animal {
bark() {
this.move()
console.log('旺旺!')
}
}
const d = new Dog()
// d.move()
8.成员可见性-private
// 父类
class Animal {
// 对于当前类来说是可见的
private __run__() {
console.log('Animal 内部辅助函数')
}
// 受保护的
protected move() {
this.__run__()
console.log('走两步')
}
// 公开的
run() {
this.__run__()
this.move()
console.log('跑起来')
}
}
const a = new Animal()
// a.
// 子类
class Dog extends Animal {
bark() {
// 对子类来说不可见
// this.
console.log('旺旺!')
}
}
const d = new Dog()
// 对子类的实例也是不可见的
// d.
9.readonly(只读修饰符)
表示只读,用来防止在构造函数之外对属性进行赋值
/* class Person {
// 只读属性
readonly age: number = 18
constructor(age: number) {
this.age = age
}
// 错误演示:
// 只能修饰属性,不能用它修饰方法
// readonly setAge() {
// // this.age = 20
// }
} */
class Person {
// 只读属性
// 注意:只要是 readonly 来修饰的属性,必须手动提供明确的类型
// 若不加类型注解,则会变为字面量类型
readonly age: number = 18
constructor(age: number) {
this.age = age
}
}
// --
// interface IPerson {
// readonly name: string
// }
// let obj: IPerson = {
// name: 'jack'
// }
let obj: { readonly name: string } = {
name: 'jack'
}
obj.name = 'rose'//报错→无法为name赋值,因为它是只读属性
类型兼容
TS采用结构化类型系统,类型检查关注的是值所具有的形状
1.语法:
// 演示类型兼容性:
// let arr = ['a', 'b', 'c']
// arr.forEach(item => {})
// arr.forEach((item, index) => {})
// arr.forEach((item, index, array) => {})
// 两个类的兼容性演示:
//只检查 Point 和 Point2D 的结构是否相同(相同,都具有 x 和 y 两个属性,属性类型也相同)
class Point {
x: number
y: number
}
class Point2D {
x: number
y: number
}
const p: Point = new Point2D()
2.更准确写法:对于对象类型来说,成员多的可以赋值给少的
// 两个类的兼容性演示:
class Point {
x: number
y: number
}
class Point2D {
x: number
y: number
}
const p: Point = new Point2D()
class Point3D {
x: number
y: number
z: number
}
const p1: Point = new Point3D()
// 错误演示
// const p2: Point3D = new Point()
3.接口兼容性
interface Point {
x: number
y: number
}
interface Point2D {
x: number
y: number
}
interface Point3D {
x: number
y: number
z: number
}
let p1: Point
let p2: Point2D
let p3: Point3D
// 正确:
// p1 = p2
// p2 = p1
// p1 = p3
// 错误演示:
// p3 = p1
// 类和接口之间也是兼容的
class Point4D {
x: number
y: number
z: number
}
p2 = new Point4D()
4.函数兼容性-函数参数个数:参数少的可以赋值给多的
// 1 参数个数: 参数少的可以赋值给参数多的
type F1 = (a: number) => void
type F2 = (a: number, b: number) => void
let f1: F1 = () => {}
let f2: F2
f2 = f1
// 错误演示:
// f1 = f2
5.函数兼容性-函数参数类型:相同位置的参数类型要相同(原始类型)或兼容(对象类型)
// 2 参数类型: 相同位置的参数类型要相同或兼容
// 原始类型:
// type F1 = (a: number) => void
// type F2 = (a: number) => void
// let f1: F1
// let f2: F2
// f1 = f2
// f2 = f1
// -------------------------
// 对象类型
interface Point2D {
x: number
y: number
}
interface Point3D {
x: number
y: number
z: number
}
type F2 = (p: Point2D) => void // 相当于有 2 个参数
type F3 = (p: Point3D) => void // 相当于有 3 个参数
let f2: F2 = () => {}
let f3: F3
f3 = f2
// f2 = f3
6.返回值类型:只关注返回值类型本身即可
// 3 返回值类型,只需要关注返回值类型本身即可
// 原始类型:
type F5 = () => string
type F6 = () => string
let f5: F5
let f6: F6
// f6 = f5
// f5 = f6
// 对象类型:
// 返回内容都是对象类型,此时按照对象自身的兼容性来理解即可
type F7 = () => { name: string }
type F8 = () => { name: string; age: number }
let f7: F7
let f8: F8
f7 = f8
// 错误演示
// f8 = f7
交叉类型
1.类似于接口继承(extends),用于组合多个类型为一个类型(常用于对象类型)
interface Person {
name: string
say(): number
}
interface Contact {
phone: string
}
type PersonDetail = Person & Contact
//新的类型 PersonDetail 就同时具备了 Person 和 Contact 的所有属性类型。
let obj: PersonDetail = {
name: 'jack',
phone: '133....',
say() {
return 1
}
}
2.交叉类型(&)和接口继承(extends)的对比:
相同:都可实现对象类型的组合
不同:对于同名属性之间,处理类型冲突的方式不同
注意:以上代码,接口继承会报错(类型不兼容);交叉类型不报错
可理解为:
泛型
在保证类型安全前提下,让函数可以与多种类型一起使用
1.基本语法:
// 1.使用泛型来创建一个函数:
function id<Type>(value: Type): Type {
return value
}
// 2.调用泛型函数:
// 2.1 以 number 类型调用泛型函数
const num = id<number>(10)
// 2.2 以 string 类型调用泛型函数
const str = id<string>('a')
const ret = id<boolean>(false)
2.简化泛型函数的调用
可以省略 <类型> 来简化泛型函数的调用→TS内部采用类型参数推断机制,可自行推断
// 1.使用泛型来创建一个函数:
function id<Type>(value: Type): Type {
return value
}
// 2.调用泛型函数:
// 2.1 以 number 类型调用泛型函数
let num1 = id(100)
// 2.2 以 string 类型调用泛型函数
let str1 = id('abc')
3.泛型约束
为泛型添加约束来收缩类型→缩窄类型取值范围
将原来可以代表任何类型的type缩窄到几个类型当中
方法:
1)指定更加具体的类型
// 将类型修改为type[]→数组一段存在length属性
function id<Type>(value: Type[]): Type[] {
value.length
return value
}
2)添加约束
interface ILength {
length: number
}
function id<Type extends ILength>(value: Type): Type {
value.length
return value
}
// 传入的类型必须具有 length 属性
id(['a', 'c'])
id('abc')
id({ length: 10, name: 'jack' })
// 错误演示
// id(123)
4.添加类型约束(使用keyof):第二个类型变量受第一个类型变量约束
// key只能是type中存在的属性和名称
function getProp<Type, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key]
}
getProp({ name: 'jack', age: 18 }, 'age')
getProp({ name: 'jack', age: 18 }, 'name')
// 补充:(了解)
getProp(18, 'toFixed')
getProp('abc', 'split')
getProp('abc', 1) // 此处 1 表示索引
getProp(['a'], 'length')
getProp(['a'], 1000)
console.log('object'[1]) // b
// 错误演示:
// getProp({ name: 'jack', age: 18 }, 'name1')
5.泛型接口
1.基本语法
interface IdFunc<Type> {
id: (value: Type) => Type
ids: () => Type[]
}
let obj: IdFunc<number> = {
//id 方法的参数和返回值类型都是 number
id(value) {
return value
},
//ids 方法的返回值类型是 number[]
ids() {
return [1, 3, 5]
}
}
2.泛型接口-数组
JS中的数组在TS中就是一个泛型接口
6.泛型类
class 也可以配合泛型来使用
// class GenericNumber<NumType> {
// defaultValue: NumType
// add: (x: NumType, y: NumType) => NumType
// constructor(value: NumType) {
// this.defaultValue = value
// }
// }
// 此时,可以省略 <类型> 不写。因为 TS 可以根据传入的参数自动推导出类型
// const myNum = new GenericNumber(100)
// myNum.defaultValue = 10
// ---------------------------------------------------------------
class GenericNumber<NumType> {
defaultValue: NumType
add: (x: NumType, y: NumType) => NumType
}
// 这种情况下,推荐明确指定 <类型>。因为 TS 无法推导出类型
const myNum = new GenericNumber()
myNum.defaultValue = 10
7.泛型工具类型:TS内置的一些常用工具类型,用来简化常用操作
1)Partial
//Partial<type>
//创建一个新类型,将type所有属性设置为可选
interface Props {
id: string
children: number[]
}
type PartialProps = Partial<Props>
let p1: Props = {
id: '',
children: [1]
}
let p2: PartialProps = {
id: '',
children: [1, 3]
}
2)Readonly
interface Props {
id: string
children: number[]
}
// Readonly<Type>
// 将所有属性设置为只读
type ReadonlyProps = Readonly<Props>
let p1: ReadonlyProps = {
id: '1',
children: [1, 3]
}
p1.id = '2'
3)Pick
interface Props {
id: string
title: string
children: number[]
}
// Pick<Type, Keys>
// 从 Type 中选择一组属性来构造新类型
//第二个类型变量传入的属性只能是第一个类型变量中存在的属性
type PickProps = Pick<Props, 'id' | 'title'>
4) Record
// Record<Keys,Type>
// 构造一个对象类型,属性键为 Keys,属性类型为 Type
// 1 表示对象有哪些属性 2 表示对象属性的类型
type RecordObj = Record<'a' | 'b' | 'c', string[]>
// type RecordObj = {
// a: string[]
// b: string[]
// c: string[]
// }
let obj: RecordObj = {
a: ['a'],
b: ['b'],
c: ['c']
}
索引签名类型
使用场景:没法直接去确定对象中有哪些属性和方法时
key只是一个占位符,可换成任意合法变量名称
注意:JS中对象({})的建是string类型
// 通过索引的写法,能够让对象接收任意的属性
interface AnyObject {
[key: string]: number
}
let obj: AnyObject = {
a: 1,
abc: 124,
abcde: 12345
}
// --
const arr = [1, 3, 5]
arr.forEach
interface MyArray<Type> {
[index: number]: Type
}
let arr1: MyArray<number> = [1, 3, 5]
arr1[0]
映射类型
1.根据联合类型创建新类型
type PropKeys = 'x' | 'y' | 'z' | 'a' | 'b'
type Type1 = { x: number; y: number; z: number; a: number; b: number }
// 表示 Key 可以是 PropKeys联合类型中的任意一个
type Type2 = { [Key in PropKeys]: number }
// 错误演示:
// interface Type3 {
// [Key in PropKeys]: number
// }
2.使用keyof创建
type Props = { a: number; b: string; c: boolean }
type Type3 = { [key in keyof Props]: number }
3.Partial实现原理
type Props = { a: number; b: string; c: boolean }
type PartialProps = Partial<Props>
4.索引查询类型:用来查询属性的类型
type Props = { a: number; b: string; c: boolean }
type TypeA = Props['a']
// 模拟 Partial 类型:
type MyPartial<T> = {
[P in keyof T]?: T[P]
}
type PartialProps = MyPartial<Props>
5.同时查询多个索引类型
type Props = { a: number; b: number; c: boolean }
// 其他使用方式:
// 获取a和b属性的类型
type TypeA = Props['a' | 'b']//string | number
// 直接获取Props中所有属性的类型
type TypeB = Props[keyof Props]//string | number | boolean
TypeScript 类型声明文件
在项目开发中使用第三方库时,几乎都有相应的TS类型,即类型声明文件
类型声明文件:用来为已存在的 JS 库提供类型信息
TS 的两种文件类型
1…ts 文件(代码实现文件)
- 既包含类型信息又可执行代码
- 可以被编译为 .js 文件,然后,执行代码
- 用途:编写程序代码的地方
2…d.ts 文件(类型声明文件)
-
只包含类型信息的类型声明文件
-
不会生成 .js 文件,仅用于提供类型信息
-
用途:为 JS 提供类型信息
// 类型声明文件 // 类型 type Props1 = { x: number; y: number } // 错误演示:因为 .d.ts 文件中,不能出现可执行代码(代码实现) // 可执行代码 // function add1(num1: number, num2: number) { // return num1 + num2 // } // console.log(add1(1, 5))
声明文件使用说明
1.使用已有的类型声明文件
1)内置类型声明文件:
TS 为 JS 运行时可用的所有标准化内置 API 都提供了声明文件
let arr = [1, 3, 5]
arr.forEach
document.querySelector
window
ctrl+鼠标左键→自动跳转到 lib.es5.d.ts 类型声明文件中
window、document 等 BOM、DOM API 也都有相应的类型声明
ctrl+鼠标左键→自动跳转到lib.dom.d.ts文件
2)第三方库的类型声明文件:
几乎所有常用的第三方库都有相应的类型声明文件
第三方库类型声明文件存在形式:
- 库自带类型声明文件:比如,axiost.md
TS 就会自动加载库自己的类型声明文件,以提供该库的类型声明
- 由 DefinitelyTyped 提供
DefinitelyTyped
是一个 github 仓库,用来提供高质量 TypeScript 类型声明- 可通过npm/yarn 来下载该仓库提供的 TS 类型声明包,包的名称格式为:@types/*
2.创建自己的类型声明文件
1.项目内共享类型:若多个.ts共有同一个类型,此时可创建**.ts文件**提供该类型,实现类型共享
1)创建 index.d.ts 类型声明文件
2)创建需要共享的类型,并使用 export 导出
3)在需要使用共享类型的 .ts 文件中,通过 import 导入即可
index.d.ts
type Props = { x: number; y: number }
export { Props }
a.ts
// a.ts
import { Props } from './index'
// type Props = { x: number; y: number }
let p1: Props = {
x: 1,
y: 2
}
b.ts
// b.ts
import { Props } from './index'
// type Props = { x: number; y: number }
let p2: Props = {
x: 10,
y: 22
}
2.为已有JS文件提供类型声明
1)在将 JS 项目迁移到 TS 项目时,为了让已有的 .js 文件有类型声明
2)成为库作者,创建库给其他人使用
utils.js
let count = 10
let songName = '痴心绝对'
let position = {
x: 0,
y: 0
}
function add(x, y) {
return x + y
}
function changeDirection(direction) {
console.log(direction)
}
const fomartPoint = point => {
console.log('当前坐标:', point)
}
export { count, songName, position, add, changeDirection, fomartPoint }
utils.d.ts
// 为 utils.js 文件来提供类型声明
// declare:为已存在的变量声明类型
declare let count: number
declare let songName: string
// 明确是TS类型,可以省略declare,如interface、type
interface Point {
x: number
y: number
}
declare let position: Point
declare function add(x: number, y: number): number
declare function changeDirection(
direction: 'up' | 'down' | 'left' | 'right'
): void
type FomartPoint = (point: Point) => void
declare const fomartPoint: FomartPoint
// 注意:类型提供好以后,需要使用 模块化方案 中提供的
// 模块化语法,来导出声明好的类型。然后,才能在
// 其他的 .ts 文件中使用
export { count, songName, position, add, changeDirection, fomartPoint, Point }
index.ts(使用)
import { count, songName, add, Point } from './utils'
type Person = {
name: string
age: number
}
let p: Partial<Person> = {
name: 'jack'
}
let p1: Point = {
x: 10,
y: 20
}
// console.log('项目启动了')
console.log('count', count)
console.log('songName', songName)
console.log('add()', add(1, 4))
已有JS文件提供类型声明**
1)在将 JS 项目迁移到 TS 项目时,为了让已有的 .js 文件有类型声明
2)成为库作者,创建库给其他人使用
utils.js
let count = 10
let songName = '痴心绝对'
let position = {
x: 0,
y: 0
}
function add(x, y) {
return x + y
}
function changeDirection(direction) {
console.log(direction)
}
const fomartPoint = point => {
console.log('当前坐标:', point)
}
export { count, songName, position, add, changeDirection, fomartPoint }
utils.d.ts
// 为 utils.js 文件来提供类型声明
// declare:为已存在的变量声明类型
declare let count: number
declare let songName: string
// 明确是TS类型,可以省略declare,如interface、type
interface Point {
x: number
y: number
}
declare let position: Point
declare function add(x: number, y: number): number
declare function changeDirection(
direction: 'up' | 'down' | 'left' | 'right'
): void
type FomartPoint = (point: Point) => void
declare const fomartPoint: FomartPoint
// 注意:类型提供好以后,需要使用 模块化方案 中提供的
// 模块化语法,来导出声明好的类型。然后,才能在
// 其他的 .ts 文件中使用
export { count, songName, position, add, changeDirection, fomartPoint, Point }
index.ts(使用)
import { count, songName, add, Point } from './utils'
type Person = {
name: string
age: number
}
let p: Partial<Person> = {
name: 'jack'
}
let p1: Point = {
x: 10,
y: 20
}
// console.log('项目启动了')
console.log('count', count)
console.log('songName', songName)
console.log('add()', add(1, 4))