ctrl+k清屏
1.安装VSCode
https://code.visualstudio.com/Download
2.安装Node.js为了安装npm
https://nodejs.org/en/download/
3.安装TypeScript编译器:npm install -g typescript
可以用tsc 文件.ts命令,根据ts生成js代码
node 文件.js 运行js
4.ts介绍
TypeScript 是 JavaScript 的类型的超集,是一种静态类型检查的语言,提供了类型批注和编译时类型检查;支持ES6语法,支持面向对象编程的概念,如类、接口、继承、泛型等; TypeScript 在编译阶段需要编译器编译成纯 JavaScript 来运行。
1.解决ts和js的冲突问题(比如命名)
tsc --init #生成配置文件 tsconfig.json
2.自动编译
tsc --watch
3.发出错误
tsc -noEmitOnError 文件.ts 提示错误并且不自动编译程js
tsconfig.json----“target”:“es5” 降级编译(考虑旧版本浏览器兼容)
strict:true 包含下面两种。是否忽略类型验证(false就会默认为any,破坏了ts类型检查)
noImplicitAny:true :不含隐藏的any(any检查,不用默认any)
strictNullChecks:true;严格空类型检验
strictPropertyInitialization:false:是否属性必须初始化(定义class),false不会检查属性
rootDirs|rootDir:ts目录
outDir:js输出目录
boolean(布尔类型)
number(数字类型)
string(字符串类型)
数组:type[]、Array泛型
any:不希望某个特定值导致类型检查错误
null 类型数据加一个!可以排除null和undefined
undefined 类型数据加一个!可以排除null和undefined
enum Name {} 枚举-一组数值赋予友好的名字
void 不返回任何值
一个具有 void返回类型的上下文函数类型(type vf = () => void),在实现时,可以返回任何其他的值,但它会被忽略。
当一个字面的函数定义有一个 void 的返回类型时,该函数必须不返回任何东西。
object:任何不是基元的值:string\number\bigint\boolean\symbol\null\undefined;不同于{},不同于Object
unknown:代表任何值。这与 any 类型类似,但更安全,因为对未知 unknown 值做任何事情都是不合法的。
never: 是其他类型 (包括null和 undefined)的子类型,可以赋值给任何类型,代表从不会出现的值,类型表示永远不会被观察到的值(抛出异常|永远不触发)
Function :全局性的 Function 类型描述了诸如 bind、call、apply和其他存在于JavaScript中所有函数值的属性。它还有一个特殊的属性,即 Function 类型的值总是可以被调用;这些调用返回 any。
tuple(元组类型):表示一个已知元素数量和类型的数组,各元素的类型不必相同。
enum(枚举类型):一组数值赋予友好的名字
: type 类型注释。可以指定具体字符、数字、true(文字类型 --有时候配合类型推断时使用)
?: type 可选类型 不传是undefined 调用方法可以用?.。可选属性使用时候在后面加个!表示肯定存在的
{x: numbr,y: number}对象
number | string 一个竖线-联合类型
type name = type 类型别名,name一般大写
类型判断 typeof对象的时候。排除null strs&&typeof
!:
!:
——表示强制解析(告诉typescript编译器,这里一定有值),常用于vue-decorator中的@Prop!:
——表示类型推断排除null、undefinedkeyof 类型操作符
type Point = { x: number; y: number };
type P = keyof Point;//这时候p是’x’|'y’联合类型
const p1:P = ‘x’
const p2:P = ‘y’
在泛型约束中使用类型参数:key extends keyof Type
function getProperty(obj: Type, key: Key) {
return obj[key]
}
let x = {
a: 1,
b: 2,
c: 3,
d: 4
}
getProperty(x, 'a')
in用来类型缩小
type Fish = { swim: () => void }
type Bird = { fly: () => void }
type Human = { swim?: () => void; fly?: () => void }
function move(animal: Fish | Bird | Human) {
if ("swim" in animal) {
// animal: Fish | Human
return (animal as Fish).swim()
}
// animal: Bird | Human
return (animal as Bird).fly()
}
不太常用的原语
const oneHundred: bigint = BigInt(100)
const anotherHundred: bigint = 100n //target:es2020才能使用
const firstName = Symbol("name")
const secondName = Symbol("name")
if (firstName === secondName) {
console.log('ok')
}
as type; 类型断言(用来转成更具体或者不太具体的版本,可以防止不可能的强制的发声)。会在编译时被删除,没有与类型断言相关联的类型检查。
//返回某种类型的HTMLElement
const myCanvas = document.getElementById ("main_canvas") as HTMLCanvasElement
const myCanvas = document.getElementById ("main_canvas")
const x = 'hello' as any
const y = 'hello' as unknown
类型别名创建后不能通过同一个名称扩展
类型使用(接口定义类型)
interface Point {
x: number;
y: number;
}
function printCoord(pt: Point) {
console.log("坐标x的值是: " + pt.x);
console.log("坐标y的值是: " + pt.y);
}
printCoord({ x: 100, y: 100 });
扩展接口
interface Animal {
name: string
}
interface Bear extends Animal {
honey: boolean
}
const bear: Bear = {
name: 'winie',
honey: true
}
console.log(bear.name)
console.log(bear.honey)
类型别名实现接口扩展效果
//交叉点实现即&
type Animal = {
name: string
}
type Bear = Animal & {
honey: boolean
}
const bear: Bear = {
name: 'winnie',
honey: true
}
向现有接口类型添加字段
//向现有的类型添加字段,会起到合并效果
interface MyWindow {
count: number
}
interface MyWindow {
title: string
}
const w: MyWindow = {
title: 'hello ts',
count: 100
}
类型别名创建后不能通过同一个名称扩展
普通定义函数类型:type GreetFunction = (a: string) => void
调用签名定义函数类型(对象方式定义)
type DescribableFunction = {
description: string //函数属性-函数可以直接调用
(someArg: number): boolean //入参(string)=>返回类型(boolean)
}
//如上类型的函数
function fn1(n: number) {
console.log(n)
return true
}
fn1.description = ‘hello’
构造签名
需要new
class Ctor {
s: string
constructor(s: string) {
this.s = s
}
}
type SomeConstructor = {
new (s: string): Ctor
}
function fn(ctor: SomeConstructor) {
return new ctor(‘hello’)
}
interface CallOrConstructor {
new (s: string): Date
(n?: number): number
}
function fn(date: CallOrConstructor) {
let d = new date(‘2021-12-20’) //构造签名
let n = date(100) //调用签名
}
泛型
编写优秀函数的三个准则
1.尽量使用本身,而不是类型约束;
2.尽量少的使用类型参数;
3.类型参数是用来关联多个值的类型的,类型如果只使用一次,每笔用用泛型
类型判断 ,
function firstElement(arr: Type[]): Type | undefined {
return arr[0]
}
firstElement([‘a’, ‘b’, ‘c’])
firstElement([1, 2, 3])
firstElement([])
限制条件
function longest
if (a.length >= b.length) {
return a
} else {
return b
}
}
const longerArray = longest([1, 2], [2, 3, 4])
指定类型参数
function combine(arr1: Type[], arr2: Type[]): Type[] {
return arr1.concat(arr2)
}
const arr = combine
console.log(arr)
可选参数
?: 可选参数;默认值:number=100
为回调写一个函数的时候,永远(尽量)不要写可选参数
函数重载
函数重载定义如何调用,函数实现才是真正的函数实现,函数实现参数得兼容函数重载
编写好的重载
总是倾向于使用联合类型的参数而不是重载参数
//函数重载 function makeDate(timestamp: number): Date
//函数重载 function makeDate(m: number, d: number, y: number): Date
//函数实现 function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d)
} else {
return new Date(mOrTimestamp)
}
}
const d1 = makeDate(12345678)
const d2 = makeDate(5, 6, 7)
const d3 = makeDate(5, 9) //报错
rest parameters 形参展开方式
//形参展开
function multiply(n: number, …m: number[]) {
return m.map( x => n * x )
}
const a = multiply(10, 1, 2, 3, 4, 60, 100)
console.log(a)
//实参展开
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
arr1.push(…arr2)
// const args = [8, 5]
// const angle = Math.atan2(…args) //报错
const args = [8, 5] as const
const angle = Math.atan2(…args)
//参数结构
type ABC = { a: number, b: number, c: number }
function sum({ a, b, c }: ABC) {
console.log(a + b + c)
}
sum({
a: 10,
b: 3,
c: 9
})
void
一个具有 void返回类型的上下文函数类型(type vf = () => void),在实现时,可以返回任何其他的值,但它会被忽略。
当一个字面的函数定义有一个 void 的返回类型时,该函数必须不返回任何东西。
type voidFunc = () => void
const f1:voidFunc = () => {
return true
}
const f2:voidFunc = () => true
const f3:voidFunc = function() {
return true
}
const v1: void = f1()
const v2 = f2()
const v3 = f3()
// 下面会报错
function f4(): void {
return true
}
const f5 = function(): void {
return true
}
定义
//匿名方式定义对象类型
function greet(person: { name: string, age: number }) {
return 'Hello ' + person.name
}
//接口方式
interface Person {
name: string
age: number
}
function greet(person: Person) {
return 'Hello ' + person.name
}
//类型别名
type Person = {
name: string
age: number
}
function greet(person: Person) {
return 'Hello ' + person.name
}
属性修改器
可选属性 :配合默认值
interface PaintOptions {
xPos?: number,
yPos?: number
}
function paintShape({ xPos: number = 0, yPos = 0 }: PaintOptions) {
// let xPos = opts.xPos === undefined ? 0 : opts.xPos
// let yPos = opts.yPos === undefined ? 0 : opts.yPos
console.log(number)
}
只读属性:readonly
加了readonly不能修改,引用对象是不能修改引用地址
readonly类型可以复制可写类型
索引签名:不能知道一个类型的所有属性名称
//索引签名只有number和string
interface StringArray {
[index: number]: string
}
const myArray: StringArray = ['a', 'b']
const secondItem = myArray[0]
interface TestString {
[props: string]: number
}
let testString: TestString = {
x: 100,
y: 200,
// aaa: 'aaa'
}
interface NotOkay {
[index: string]: number | string
length: number
name: string
}
let notOkay: NotOkay = {
x: 100,
length: 100,
name: 'felix'
}
扩展类型
interface Colorful {
color: string
}
interface Circle {
radius: number
}
interface ColorCircle extends Colorful, Circle {}
const cc: ColorCircle = {
color: 'red',
radius: 100
}
交叉类型
interface Colorful {
color: string
}
interface Circle {
radius: number
}
type ColorfulCircle = Colorful & Circle
const cc: ColorfulCircle = {
color: 'red',
radius: 100
}
扩展类型和交叉类型主要区别
interface可以重名合并,类型别名可以避免命名冲突
泛型类型对象
// interface Box {
// contents: Type
// }
// 通用类型 以下写法很好
type OrNull = Type | null
type OneOrMany = Type | Type[]
type OneOrManyOrNull = OrNull>
type OneOrManyOrNullString = OneOrManyOrNull
泛型*
function identity(arg: Type): Type {
return arg
}
identity("string")
identity("string")
//泛型类型
let myIdentity: (arg: Type) => Type = identity
let myIdentity: (arg: Input) => Input = identity
let myIdentity: { (arg: Type): Type } = identity
interface GenericIdentityFn {
(arg: Type): Type
}
let myIdentity: GenericIdentityFn = identity
interface GenericIdentityFn {
(arg: Type): Type
}
let myIdentity: GenericIdentityFn = identity
//泛型类
class GenericNumber {
zeroValue: NumType
add: (x: NumType, y: NumType) => NumType
}
let myGeneric = new GenericNumber()
myGeneric.zeroValue = 0
myGeneric.add = function (x, y) {
return x + y
}
//泛型约束
类型必须有extends里面的属性
interface Lengthwise {
length: number
}
//Type必须有length属性
function loggingIdentity(arg: Type): Type {
arg.length
return arg
}
loggingIdentity(['hello', 'world'])
//在泛型约束中使用类型参数
key extends keyof Type
key类型一定属于Type类型的某个key
function getProperty(obj: Type, key: Key) {
return obj[key]
}
let x = {
a: 1,
b: 2,
c: 3,
d: 4
}
getProperty(x, 'a')
//在泛型中使用类类型
c是个类类型
c: { new (): Type }
function create(c: { new (): Type }): Type {
return new c()
}
class BeeKeeper {
hasMask: boolean = true
}
class ZooKeeper {
nametag: string = 'Mikle'
}
class Animal {
numLegs: number = 4
}
class Bee extends Animal {
keeper: BeeKeeper = new BeeKeeper()
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper()
}
function createInstance(c: new () => A): A {
return new c()
}
createInstance(Lion).keeper.nametag
createInstance(Bee).keeper.hasMask
createInstance(BeeKeeper)//类型约束不是没有Animal的属性
keyof 类型操作符
// type Point = {
// x: number,
// y: number
// }
// type P = keyof Point
// const p1:P = 'x'
// const p2:P = 'y'
// const p3:P = 'z'
type Arrayish = {
[n: number]: unknown
}
type A = keyof Arrayish
const a:A = 0
type Mapish = {
[k: string]: boolean //索引类型是string可以是number或者string
}
type M = keyof Mapish
const m1:M = 's'
const m2:M = 100
typeof类型操作符
let s = 'hello'
let n: typeof s //返回s类型
n = 'hello'
n = 100
// type Predicate = (x: unknown) => boolean
// type K = ReturnType
// function f() {
// return {
// x: 10,
// y: 3
// }
// }
// type P = ReturnType //类型是{x:number,y:number}
索引访问类型 //索引的时候只能使用类型
// type Person = {
// age: number,
// name: string,
// alive: boolean
// }
// type Age = Person['age']
// let age: Age = '90'
interface Person {
name: string
age: number
alive: boolean
}
// type I1 = string | number
type I1 = Person['age' | 'name']
const i11: I1 = 100
const i12: I1 = ''
// const i13: I1 = true
// type I2 = string | number | boolean
type I2 = Person[keyof Person]
const I21: I2 = ''
const I22: I2 = 100
const I23: I2 = true
// const I24: I2 = {}
type AliveOrName = 'alive' | 'name'
type I3 = Person[AliveOrName]
const I31: I3 = true
const I32: I3 = 'hello'
// const I33: I3 = 100
// type I4 = Person['alve']
const MyArray = [
{ name: 'Alice', age: 15 },
{ name: 'Bob', age: 23 },
{ name: 'Eve', age: 38 }
]
// type Person = { name: string, age: number }
type Person = typeof MyArray[number]
const p:Person = {
name: 'xiaoqian',
age: 11,
// alive: true
}
type Age = typeof MyArray[number]['age']
const age: Age = 11
type Age2 = Person['age']
const age2: Age2 = 300
// const key = 'age'
type key = 'age'
type Age3 = Person[key]
条件类型
interface Animal {
live(): void
}
interface Dog extends Animal {
woof(): void
}
// type Example1 = number
type Example1 = Dog extends Animal ? number : string
// type Example2 = string
type Example2 = RegExp extends Animal ? number : string
条件类型约束
// type MessageOf = T['message']
// type MessageOf = T['message']
type MessageOf = T extends { message: unknown } ? T['message'] : never
interface Email {
message: string
}
interface Dog {
bark(): void
}
// type EmailMessageContents = string
type EmailMessageContents = MessageOf
const emc: EmailMessageContents = 'balabala...'
type DogMessageContents = MessageOf
const dmc: DogMessageContents = 'error' as never
//在条件类型内推理 infer
type GetReturnType = Type extends (...args: never[]) => infer Return
? Return
: never
// type Num = number
type Num = GetReturnType<() => number>
let num: Num = 100
// type Str = string
type Str = GetReturnType<(x: string) => string>
let str: Str = ''
// type Bools = boolean[]
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>
let bools: Bools = [true, false]
// type Never = never
type Never = GetReturnType
let nev: Never = 'error' as never
分布式条件类型
type ToArray = Type extends any ? Type[] : never
// type StrArrOrNumArr = string[] | number[]
type StrArrOrNumArr = ToArray
let saon: StrArrOrNumArr = [1,2,3]
type ToArrayNonDist = [Type] extends [any] ? Type[] : never
//type StrArrOrNumArr = (string | number)[]
type StrArrOrNumArr = ToArrayNonDist
let saon: StrArrOrNumArr = [1,'22']
类属性
class Point {
x
y
constructor() {
this.x = 0
this.y = 0
}
}
const pt = new Point()
pt.x = 1
pt.y = 1
console.log(pt.x)
console.log(pt.y)
class OkGreeter {
name!: string//类型断言可以不初始化.表示强制解析(告诉ts编译器,这里一定有值)
}
readonly
class Greeter {
readonly name: string = 'world'//只可以在构造器初始化
constructor(otherName?: string) {
if (otherName !== undefined) {
this.name = otherName
}
}
err() {
// this.name = 'not ok'
}
}
const g = new Greeter('hello')
// g.name = 'a'
构造器
class Point {
x: number
y: number
constructor (x: number = 0, y: number = 0) {
this.x = x
this.y = y
}
}
方法
类内部读取属性要加this
class Point {
x: number = 10
y: number = 10
scale(n: number): void {
this.x *= n
this.y *= n
}
}
const p = new Point()
p.scale(10)
console.log(p.x)
console.log(p.y)
Getters / Setters
如果存在 get,但没有set,则该属性自动是只读的
如果没有指定setter参数的类型,它将从getter的返回类型中推断出来
访问器和设置器必须有相同的成员可见性
class C {
_length = 0
get length() {
return this._length
}
set length(value) {
this._length = value
}
}
let c: C = new C()
console.log(c.length)
c.length = 100
c.length = 'hello'
console.log(c.length)
索引签名
class MyClass {
[s: string]: boolean | ((s: string) => boolean)
//属性
x = true
//函数
check(s: string) {
return this[s] as boolean
}
}
类继承-implements子句
//实现类型不一定与接口类型一致;可选属性可以不实现
interface Checkable {
check(name: string) : boolean
}
class NameChecker implements Checkable {
//check(s: string|number) {
check(s: string) {
return s.toLowerCase() === 'ok'
}
}
extends
//基类
class Animal {
move() {
console.log('Moving along!')
}
}
//派生类,基类的子类型
class Dog extends Animal {
woof(times: number) {
for (let i = 0; i < times; i++) {
console.log('woof!')
}
}
}
const d = new Dog()
d.move()
d.woof(3)
方法重写
//派生类是基类的子对象|子类型
//派生类同名方法覆盖基类方法。
//派生类一定要和基类做兼容。
//greet(name: string)这样子就不兼容基类
class Base {
greet() {
console.log('Hello World')
}
}
class Derived extends Base {
greet(name?: string) {
if (name === undefined) {
super.greet()
} else {
console.log(name.toUpperCase())
}
}
}
const d = new Derived()
d.greet()
d.greet('reader')
//派生类是基类的子对象|子类型
const b: Base = d
初始化顺序
基类的字段被初始化
基类构造函数运行
派生类的字段被初始化
派生类构造函数运行
继承内置类型
//es5兼容性解决
class MsgError extends Error {
constructor(m: string) {
super(m)
// 明确的设置原型
Object.setPrototypeOf(this, MsgError.prototype)
}
sayHello() {
return 'hello ' + this.message
}
}
const msgError = new MsgError('hello')
console.log(msgError instanceof MsgError)
成员的可见性
public(默认):公开的,默认值。任何对象在任何地方都可以访问(类内部,子类,实例上)
protected:受保护的。能在当前类或者子类中进行访问
子类中可以修改父类中某个属性的可见性
class Base {
protected m = 10
}
class Derived extends Base {
public m = 15
}
const d = new Derived()
console.log(d.m)
private:私有的。只能在当前类中进行访问,不允许子类、实例访问
静态成员
不需要实例化,直接通过类名访问。
静态成员可以继承,可以配合可见性使用
class MyClass {
private static x = 0
static printX() {
console.log(MyClass.x)
}
}
console.log(MyClass.x)
MyClass.printX()
class Base {
static getGreeting() {
return 'hello world'
}
}
class Derived extends Base {
myGreeting = Derived.getGreeting()
}
类里的static区块
//仅能类内部使用
class Foo {
static #count = 0
get count() {
return Foo.#count
}
static {
try {
const lastInstance = {
length: 100
}
Foo.#count += lastInstance.length
}
catch {}
}
}
//以下调用报错
//Foo.#count
泛型类
静态成员不能赋值泛型
class Box {
contents: Type;
constructor(value: Type) {
this.contents = value;
}
}
const b = new Box("hello!")
类运行时候的this
// 解决this指向问题:1.箭头函数(得保证this正确;比较耗内存,类实例得有副本;不能在派生类中使用super调用父类方法,原型链中无法获取基类方法);2.this参数(每个类定义只有一个函数被分配,而不是每个实例创建一个函数;可以super调用)
class MyClass {
name = 'MyClass'
//getName() {
// return this.name
//}
// getName = () => { //解决方案1
// return this.name
// }
//getName(this: MyClass) {//解决方案2//谁调用就访问谁
// return this.name
//}
}
const c = new MyClass()
// console.log(c.getName()) //'MyClass'
// const obj = {
// name: 'obj',
// getName: c.getName
// }
// console.log(obj.getName())//'obj'
const g = c.getName
// console.log(c.getName())
console.log(g())
this类型
派生类后基类的this依旧指向派生类
基于类型守卫的this
this is Type ;this配合守卫可以缩小类型
class FileSystemObject {
isFile(): this is FileRep {
return this instanceof FileRep
}
isDirectory(): this is Directory {
return this instanceof Directory
}
isNetworked(): this is Networked & this {
return this.networked
}
constructor (public path: string, private networked: boolean) {}
}
class FileRep extends FileSystemObject {
constructor(path: string, public content: string) {
super (path, false)
}
}
class Directory extends FileSystemObject {
children: FileSystemObject[]
constructor() {
super('', false)
this.children = []
}
}
interface Networked {
host: string
}
const fso: FileSystemObject = new FileRep('foo/bar.txt', 'foo')
if (fso.isFile()) {
// const fso: FileRep
fso.content
} else if (fso.isDirectory()) {
// const fso: Directory
fso.children
} else if (fso.isNetworked()) {
// const fso: Networked & FileSystemObject
fso.host
}
class Box {
value?: T
hasValue(): this is { value: T } {
return this.value !== undefined
}
}
const box = new Box()
box.value ='hello'
if (box.hasValue()) {
console.log(box.value)
}
参数属性
构造函数入参属性前加入修饰符:public readonly,protectd,private
class Params {
constructor (public readonly x: number, protected y: number, private z: number) {
this.x = x
}
}
const p = new Params(100, 300, 400)
console.log(p.x)
// p.x = 200
//p.y
//p.z
类表达式
const someClass = class {
content: Type
constructor(value: Type) {
this.content = value
}
}
const m = new someClass('hello')
console.log(m.content)
抽象类和成员
abstract:没有提供实现的方法或者字段,这些成员必须存在于一个抽象类中。不能直接实例化,抽象类的作用是作为子类的基类,实现所有抽象成员。
当一个类没有抽象成员时,我们就说他是具体的。
abstract class Base {
abstract getName(): string
printName() {
console.log(this.getName())
}
}
class Derived extends Base {
getName () {
return 'world'
}
}
const b = new Derived()
b.getName()
b.printName()
function greet(ctor: new() => Base) {
const instance = new ctor()
instance.printName()
}
greet(Derived)
类之间的关系
//类属性和类型一样
class Point1 {
x = 0
y = 0
}
class Point2 {
x = 0
y = 0
}
const p: Point1 = new Point2()
//Emplyee 是 Person子类
class Person {
name: string = ''
age: number = 100
}
class Emplyee {
name: string = 'felixlu'
age: number = 23
salary: number = 10
}
const p: Person = new Emplyee()
在TypeScript中编写基于模块的代码时,有三个主要方面需要考虑:
语法:我想用什么语法来导入和导出东西?
模块解析:模块名称(或路径)和磁盘上的文件之间是什么关系?
模块输出目标:我编译出来的JavaScript模块应该是什么样子的?
es模块化
//导出1
export default function helloWorld() {
console.log('Hello, World')
}
//导出2
export var pi = 3.14
export let squareTwo = 1.41
export const phi = 1.61
export class RandomNumberGenerator {}
export function absolute(num: number) {
if (num < 0) return num * -1
return num
}
//导入
import hello from './hello'
import { pi, phi, absolute } from './maths'
hello()
console.log(pi)
console.log(absolute(phi))
额外的导入语法
//导出
export const pi = 3.14
export default class RandomNumberGenerator {}
//导入起别名
import RNGen, { pi as π } from './maths'
//import * as math from './maths'
const rnGen = new RNGen()
//console.log(math.pi)
//const rnGen = new math.default()
typeScript特定的es模块语法
//导出
export type Cat = {
breed: string
yearOfBirth: number
}
// export type Dog = {
// breeds: string[]
// yearOfBirth: number
// }
export const createCatName = () => 'fluffy'
export interface Dog {
breeds: string[]
yearOfBirth: number
}
//导入
import type { Cat, Dog } from './animal'
import { createCatName } from './animal'
import { createCatName, type Cat, type Dog } from './animal'
type Animals = Cat | Dog
createCatName()
commonJs语法
//导出module.exports;exports
function absolute(num: number) {
if(num < 0) return num * -1
return num
}
module.exports = {
pi: 3.14,
squareTwo: 1.41,
phi: 1.61,
absolute
}
// exports.absolute = absolute
//导入
const maths = require('./maths')
console.log(maths.pi)