TypeScript 笔记

TypeScript是拥有类型的JavaScript超集,它可以编译成普通、干净、完整的JavaScript代码

TypeScript的编译环境

`ts-> js -> 浏览器运行`
1. 安装 npm install typescript -g
2. 查看版本 tsc -v
3. tsc '跟当前ts文件进行编译'

`搭建ts环境的两种方案`
1. 通过webpack搭建一个ts环境
	npm install ts-loader typescript -D
	'webpack.config.js配置'
	module: {
        rules: [
            {
                test: '/\.ts$/',
                loader: 'ts-loader'
            }
        ]
    }
    
	`tsc --init` -> 生成tsconfig.json文件

2. 通过安装'npm install ts-node -g'  ts-node TypeScript.ts   编译->运行在node上面
     还要依赖两个包, npm install tslib @types/node -g

变量的声明

1. '声明类型后ts会进行类型检测,声明的类型可以称之为类型注解'
`格式 var/let/const 标识符:数据类型 = 赋值`
const name: string = 'coder'
var age: number = 12
let height: number = 1.99

2. 'string和String的区别'
// string : ts中的字符串类型
// String : js中的字符串包装类的类型

3. '类型推导/推断'
let foo = 'foo'
// foo此时就是字符串类型

基本数据类型

1. '数字类型  number'
// 整数型,和浮点型统称为数字类型
let num: number = 123
num = 222
let num1: number = 100 // 十进制
let num2: number = 0b100 // 二进制
let num3: number = 0o105 // 八进制
let num4: number = 0x100abf // 十六进制

2. '布尔类型 boolean 取值true或者false'
let flag: boolean = true
flag = false

3. '字符串类型 string'
let message = 'hello world'
let message1 = `name: ${name}`

4. '数组类型 Array'
const names1 = Array<string> = ['abc'] // 不推荐(react jsx中有冲突 <div><div>)
const names2 = string[] = ['abc', 'cdb'] // 推荐
names1.push('sth')

5. '对象类型 Object'
// 会自动推导出里面值的类型
const info = {
    name: 'why',
    age: 18
}

6. 'null类型 值只能null'
const n1: null = null 

7. 'undefined类型 值只能undefined'
let n2: undefined = undefined

8. 'Symbol类型'
const title1 = Symbol('title')
const title2 = Symbol('title')
const info = {
    [title1]: '处女是'
    [title2]: '老老师'
}
info[title1]

ts的数据类型

1. 'any类型 任意类型'
// 无法确定变量类型,并且可能它会发生一些变化,可以使用any类型
// 不想给js添加具体的数据类型时可以使用any
// any 类型可以赋值给任意类型
let message: any = 'hello world'
message = 123
message = true
message = {}

2. 'unknown类型'
// 描述类型不确定的变量
// unknown类型只能赋值给any和unknown类型
function foo() { return 'abc' }
function bar() { return 123 }
let flag:boolean = true
let result: unknown
if(flag) {
    result = foo()
} else {
    result = bar()
}

3. 'void类型'
// 当一个函数没有返回值的时候就是void类型,或者加上ovid类型
function foo(num1: number, num2: number):ovid {
    return null 或者 undefined // 当加上ovid类型,可以返回null或者undefined
}
foo(10,20)

4. 'never类型'
// 永远不会发生值的类型
function foo(): never {
    while(true) {
        // 死循环,永远没有返回值
    }
}
function bar(): never {
    throw new Error()
}

5. '元组类型 tuple'
// 多种元素的组合
const info: [string, number, number] = ['bac', 18, 18.9]

6. '函数的数据类型 '
// 给参数添加类型注解和 (num: number)
// 返回值加类型注解 () : number
// 在开发中,通常情况可以不写返回值类型(自动推导)
function sum(num1: number, num2: number): number {
    return num1 + num2
}
`匿名函数的参数类型`
const names = ['abc', 'sfc', 'sdaf']
// item根据上下文的环境推导出来的,可以不加类型注解
// 上下文中的函数:可以不添加类型注解
names.forEach(function(item) => {})

7. '对象类型'
// point: x/y -> 对象类型
// {x: number, y: number}
function printPoint(point: {x: number, y: number}) {
    console.log(point.x, point.y)
}
printPoint({x: 123, y: 321})

8. '可选类型'
// point: x/y/z -> 对象类型
// {x: number, y: number, z?: number}
function printPoint(point: {x: number, y: number, z?: number}) {
    console.log(point.x, point.y)
}
printPoint({x: 123, y: 321})
printPoint({x: 123, y: 321, z: 2143})

9. '联合类型 union type'
// ts的类型系统允许我们使用多种运算符,从现有的类型中构建新类型
// number|string
function printID(id: number | string) {
    console.log(id)
}
printID(123)
printID('ads')

10. '类型别名 type alias'
type IDType = string | number | boolean
type PointType = {
    x: number
    y: number
    z: number
}
function printId(id: IDType) {}
function printId(id: PointType) {}

11. '类型断言 as'
// ts无法获取具体类型信息,这时就需要类型断言
// 关键字 as 将宽泛的类型,转换成具体的类型
const el = document.getElementById('hty') as HTMLImageElement
el.src = 'url地址'

12. '非空类型断言'
// 关键字 ! 一定有值
function fo(message?: string) {
    cosole.log(message!.length)
}
fo()
fo('1324')

13. '可选链 es11新特性'
// 关键字 ?.
// 当对象属性不存在时,会短路,直接返回undefined,如果存在,那么会继续执行
type person {
    name: string,
    friend?: {
        name: string
    }
}
const info : person = {
    name: 'wht',
    friend: {
        name: 'kobe'
    }
}
console.log(info.friend?.name) // 没有就取的是undefined

            
14 '!! 和 ?? 运算符'
// !! 操作符 将其他类型转成boolean类型
// ?? 操作符 当操作符左侧是null 或者 undefined时,返回其右侧操作数,否则返回左侧
{}


15. '字面量类型'
// 'Hello World' 也可以作为类型,叫字面量类型
const message: 'Hello World' = 'Hello World'

let align: 'left' | 'right' | 'height' = 'left'
align = 'right'

16. '字面量推理'
const info = {
    url: 'http: 4300',
    method: 'GET'
}
function request(url: string, method: 'GET' | 'POST') {}
    request(info.url, info.method)
// 这是因为我们的对象再进行字面量推理的时候,info其实是一个{url: string, method: string),所以我们没办法将一个string赋值给一个字面量类型。

`解决方法1`
    request(info.url, info.method as "GET")
`解决方法2`
const info = {
    url: 'http: 4300',
    method: 'GET'
} as const


17. '类型缩小'
// typeof padding === 'number' 的判断语句在执行路径中,缩小声明更小的类型,称为缩小
`常见类型保护`
typeof
等平缩小 === !== 
instanceof
in 
`例子`
type IDType = number | string
function PrintID(id: IDType) {
    if(typeof id === 'string') {}
    if()
}
    
18. '函数类型'
`在作为参数时, () => void`
function bar (fn: () => void) {
    fn()
}
bar(foo)
`定义常量时,编写函数的类型`
type AddFnType = (num1: number, num2: number) => number
const add: AddFnType = (a1: number, a2: number) => {
    return a1 + a2
}

19. '对this类型的处理'
type ThisType = { name: string }
function eating(this: ThisType) {
    console.log(this.name + '123')
}
const info = {
    name: 'why',
    eating: eating
}
info.eating()
eating.call({name: 'kobe'})
eating.apply({name: 'james'})
    
20. '函数的重载'
`函数的重载: 函数名称相同,但是参数不同的几个函数,就是函数的重载`
// 重载函数
function add(num1: number, num2: number): number
function add(num1: string, num2: string): string
// 实现函数
function add(num1: any, num2: any): any {
    return num1 + num2
}
// 先去匹配声明的函数,然后在到函数的实现里去执行函数体
const result = add(10, 290) 
const result = add('曾环','酒仙')
// 在函数的重载中,实现函数是不能直接被调用的
add({name: 'why'}, {age: 18}) // 报错

面向对象--类

1. `类的定义`
'关键字 class申明类'
'new 实例化类'
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('智能化', 12)

2. `类的继承`
'关键字 extends 继承父类的属性和方法'
'关键字 super 调用父类的构造器constructor'
// 父类
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
    }
	// 子类对父类方法的重写
	eating() {
        // 使用super可以调用父类的方法执行一次
        super.eating()
    }
	studying() {
        console.log('studying')
    }
}
const stu = new Student('why', 18, 111)


3. `类的多态`
'父类引用指向子类对象'
class Animal {
    action() {
        console.log('123')
    }
}
class Dag extends Animal {
    action() {
        console.log('234')
    }
}
class Fish extends Animal {
    action() {
        console.log('234')
    }
}
// 多态的目的是为了写出更加具备通用性的代码
function make(animals: Animal[]) { // Animal[]父类类型,指向子类对象new Dag()
    animals.forEach(animal => {    // 所以执行的是子类的方法,这就是多态
        animals.action()
    })
}
make([new Dag(), new Fish()])

4. `TS中类的成员修饰符`
'public 修饰的是任何地方可见,公有的属性和方法,默认编写的属性就是public'
'private 修饰的是仅在同一类中可见,私有的属性和方法'
'protected 修饰的是仅在类自身及子类中可见,受保护的属性和方法'
class Person {
    private name: string = ''
    getName(name) {
        // private只能在类内部访问,外部不能访问
        return this.name = name
    }
}

class Person {
    protected name: string = ''
}
class Student extends Person {
    getName() {
        // protected可以在类内部和子类中访问,外部不能访问
        return this.name
    }
}

5. `只读属性 readonly`
'只读属性是可以在构造器中赋值,赋值后就不可以修改了'
'属性本身是不能修改,但是如果它是对象类型,对象中的属性是可以修改的'
class Person {
    readonly name: string 
    constructor(name: string) {
        this.name = name
    }
}
const p = new Person()
p.name = 'sdf' // 这里是不能修改的

6. `getter和setter`
class Person {
    private _name: string
    constructor(_name: string) {
        this._name = name
    }
	// 访问器
	set name(newName) {
        this._name = newName
    }
	get name() {
        return this._name
    }
}
const p = new Person('why')
p.name = '123'
console.log(p.name) // 可以直接访问

7. `类的静态成员`
'不需要new 实例,可以直接访问的成员'
class Student {
    static time: string = "10:10"
	static attendClass() {
        
    }
}
console.log(Student.time)

8. `抽象类abstract`
'继承是多态使用的前提'
'所以在定义很多通用的调用接口时,我们通常会让调用者传入父类,通过多态来实现更加灵活的调用方式。'
'但是,父类本身可能并不需要对某些方法进行具体的实现,所以父类中定义的方法。,我们可以定义为抽象方法。'
// 抽象类不能被实例化
// 抽象方法可以没有函数体,必须要被子类实现,否则该类必须是一个抽象类
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
    }
}

9. `类的类型`

class Person {
    name: string = '123'
	eating() {}
}
const p = new Person() // p类的类型就是Person类
const P1: Person = {
    name: 'why',
    eating() {}
}
// 使用
function PrintPerson(p: Person) {
    console.log(p.name)
}
printPerson(new Person())
printPerson({ name: 'kobe', eating: function() {}})

接口

1. `接口的声明`
'关键字 interface'
// 声明对象类型,和type声明差不多
// 在接口名字前面加一个 I 命名规范
// 在接口可以定义可以定义可选类型
// 也可以定义只读属性
interface InfoType {
    readonly name: string
    age: number
    friend?: {
       name: string
    }
}
const info: InfoType = {
    name: 'why',
    age: 18
}

2. `索引类型`
// 通过interface来定义索引类型
interface IndexLanguage {
    [index: number] : string
}
const fronLanguage: IndexLanguage = {
    0: 'HTML',
    1: 'css',
    2: 'javascript'
}

interface ILanguageYear {
    [name: string] : number
}

3. `函数类型`
// 可调用的接口
interface CalcFn {
    (n1: number, n2: number): number
}

4. `接口的继承`
interface ISwim {
    swimming: () => void
}
interface IFly {
    flying: () => void
}
interface IAction extends ISwim, IFly {}
    
const action: IAction = {
    swimming() {},
    flying() {}
}
    
5. `交叉类型`
interface ISwim {
    swimming: () => void
}
interface IFly {
    flying: () => void
}
type MyType1 = ISwim | IFly
type MyType2 = ISwim & IFly    

const obj1: MyType1 = {
    flying() {}
    swimming() {}
}
    
6. `接口的实现`
interface ISwim {
    swimming: () => void
}
interface IFat {
    eating: () => void
}
    // 类实现接口
class Animal {
    
}
// 继承: 只能实现单个继承
// 实现: 实现接口,类可以实现多个接口
class Fish extends Animal implements ISwim, IEat {
    swimming() {}
    eating() {}
}
// 编写一个公共的api: 面向接口编程
function swimAction(swimable: ISwim) {
    swimable.swimming()
}
// 所有实现了接口的类对应的对象,都可以传入
swimAction(new Fish())
swimAction({swimming: function() {}})

interface和type的区别

`我们会发现interface和type都可以用来定义对象类型,那么在开发中定义对象类型时,到底选择哪一个呢?`
1. 如果是定义非对象类型,通常推荐使用type,比如Direction、Alignment、一些Function ;`如果是定义对象类型,那么他们是有区别的`:
1.interface可以重复的对某个接口来定义属性和方法;
2.而type定义的是别名,别名是不能重复的;

补充字面量赋值

interface IPerson = {
    name: string
    age: number
}
const info {
    name: 'why',
    age: 18,
    address: '关东'
}
// 是可用通过类型检测的,会先把多余的擦除进行类型检测,
const p: IPerson = info

枚举类型

`枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型;` 

`枚举允许开发者定义一组命名常量,常量可以是数空、字符串类型:`
1. `枚举类型的使用`
'关键字 enum'
enum Direction {
    LEFT,
    RIGHT,
    TOP,
    HEIGHT
}
function turnDirection(directon: Direction) {
    switch(directon) {
            case Direction.LEFT
            console.log('向左')
            break
    }
}

turnDirection(Direction.LEFT)


2. `枚举类型的值`
enum Direction {
    LEFT = 100,
    RIGHT = 200,
}

泛型

`泛型就是类型参数化`
1. `使用泛型`
function sum<Type>(num1: Type, num2: Type): Type {
    return 
}
sum<number>(10,20)
sum<string>('10','20')

2. `泛型接口的使用`
interface IPerson<T1, T2=string> {
    name: T1,
    age: T2
}
const p: IPerson<number, number> {
    name: 'why',
    age: 18
}

3. `泛型类的使用`
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('2','22','33')
const p2 = new Point<string>('2','22','33')
const p3: Point<string> = new Point('2','22','33')

4. `泛型的类型约束`
'通过extends进行约束'
interface Ilength {
    length: number
}
function getLength<T extends ILength>(arg: T) {
    return arg.length
}

.d.ts文件配置

`声明模块`
declare module 'loadsh' {
    export function join(arr: any[]): void
}
    
`声明变量/函数/类`
declare let whyName: string
declare let whyAge: number

declare function whyFoo(): void

declare class Person {
    name: string
    age: number
}

`声明文件`
declare module '*.jpg'
declare module '*.svg'

`声明命名空间`
// 这里相当于全局的
declare namespace $ {
    export function ajax(settings: any): any
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

派大星965

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值