TypeScript学习笔记

环境搭建:

npm i -g typescript

npm i -g ts-node

报错console

Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include

 解决方式:

npm install -g  @types/node

自定义类型:

interface Xiaojiejie {
    uname: string,
    age: number
}

const xiaohong: Xiaojiejie = {
    uname: '小红',
    age: 18
}

console.log(xiaohong.age)

ts静态类型分为基础静态类型和对象静态类型

// 基础静态类型
const count: number = 10
const name: string = 'cutaoki'
// 对象类型
// 对象
const Xiaojiejie: {
    name: string,
    age: number
} = {
    name: 'zxy',
    age: 20
}
// 数组
const arr: string[] = ['lzp', 'zxy']
// 类/构造函数
class Person{}
const ppl: Person
// 函数
const fn: () => string = () => 'couple'  //这里规定必须是一个函数并且返回值必须是字符串

ts在可以自动分析变量类型情况下无需类型注解;但是如果无法分析,则需要使用类型注解

let count = 123

如果函数传入参数为对象,给对象属性添加类型注解要注意写法

function add({num1, num2} : {num1 : number, num2 : number}) {
    return num1 + num2
}
const total = add ({num1 : 11, num2 : 12})

函数返回值类型注解

function getTotal(one : number, two : number): number {
    return one + two + ''
}
const total = getTotal(1, 2)

在getTotal函数申明时,限制了返回值类型,这样就会报错。需将函数内的 + ' ‘删掉即可

返回类型 

        void  表示没有任何返回值,即使是空字符串也会报错

        never  表示永远不会有值的一种类型(比如抛出异常或根本就不会有返回值的类型或死循环)

        any  表示可以是任何类型

数组类型注解

const numArr : number[] = [1, 2, 3]
const strArr : string[] = ['a', 'b', 'c']
const undArr : undefined[] = [undefined, undefined]
const mixArr : (number | string)[] = [1, 'b', 3]
const objArr : {name: string, age: number}[] = [  //也可以用定义好的接口、类型别名或类,形式如:Model1[]
    {name: 'taylor', age: 16},
    {name: 'crystal', age: 18}
]
//~~~~~~~~~~~~~~~~~~~~~
//type alias  类型别名
//接口与类型别名很相似,区别是类型别名可以直接赋值类型,而接口必须是对象
type Lady = {name: string, age: number}
const objArr : Lady[] = [
    {name: 'taylor', age: 16},
    {name: 'crystal', age: 18}
]
//~~~~~~~~~~~~~~~~~~~~~
//类
class Madam {
    name: string;
    age: number;
}
const objArr : Madam[] = [
    {name: 'taylor', age: 16},
    {name: 'crystal', age: 18}
]

上面如果用类作为数组前类型限制时,会报错Property has no initializer and is not definitely assigned in the constructo如图

错误原因:
在Typescript 2.7 release版本出来后,设置了一个新的编译器选项strictPropertyInitialization。
当本选项 strictPropertyInitialization:true 的时候,编译器会确保一个类中所有的属性都已经初始化,如果没有,那么在属性构建的过程中就会抛出错误。

解决办法(来自https://www.jianshu.com/p/cec1add8ddf0):

//1
class Model1 {
    name!: string;
    age!: number;
}
const objArr: Model1[] = [
    {name: 'taylor', age: 16},
    {name: 'crystal', age: 18}
]


//2 在构造器里面为变量赋予一个默认值
class Model1 {
    name: string;
    age: number;
    constructor() {
        this.name = '',
        this.age = 0
    }
}
const objArr: Model1[] = [
    {name: 'taylor', age: 16},
    {name: 'crystal', age: 18}
]


//3
class Model1 {
    name: string;
    age: number;
    constructor(name: string, age: number) {
        this.name = name,
        this.age = age
    }
}
const objArr: Model1[] = [
    {name: 'taylor', age: 16},
    {name: 'crystal', age: 18}
]


//4
class Model1 {
    constructor(public name: string, public age: number) {}
}

const objArr: Model1[] = [
    {name: 'taylor', age: 16},
    {name: 'crystal', age: 18}
]

元组(类似固定成员类型顺序的数组,完美配合CSV使用)

const tuple: [string, number, string] = ['crystal', 18, 'actor']

元组也可以作为数组的成员类型注解

const tupleArr: [string, number, string][] = [
    ['crystal', 18, 'actor'],
    ['taylor', 16, 'singer'],
    ['yang', 20, 'dancer'],
]

类(与es6的类很相似)

子类中调用父类的属性或方法,在前面加上  super.  ,例如父类有个say方法,在子类想调用就要用super.say()

三个关键字:public  默认,允许类的内部和外部使用

                      private  只允许在类的内部使用

                      protected  在私有的范围之外还可以在子类中使用,即继承自这个类的子类内部

对于private属性,可以用get和set暴露给类的外部

class Person {
    constructor(private _age: number) {}
    get getAge() {
        return this._age-3
    }
    set setAge(age: number) {
        this._age = age + 5
    }
}

const someone = new Person(18)
someone.getAge()
someone.setAge(30)
someone.getAge()

还有一个关键字static,在属性或者方法前面加上static后就是静态属性/静态方法,可以不用创建实例,而通过类点静态属性/静态方法调用。

还有一个关键字readonly,表示只读属性,一旦赋值就没法修改。

class Person {
    public readonly _name: string
    constructor(name: string) {
        this._name = name
    }
}

const crystal= new Person('cc')
console.log(crystal._name)

如果子类有构造函数constructor,子类必须调用super方法

class Person {
    constructor(public name: string){
    }
}

class Teacher extends Person {
    constructor(public age: number) {
        super('cutaoki')  // 如果父类没有constructor函数,就不用传参
    }
}

const xiaocang = new Teacher(28)
console.log(xiaocang.name + xiaocang.age)

抽象类

abstract class Girl {
    abstract job()  //抽象类中的方法必须是抽象方法,而且不需要大括号写具体逻辑
                    //抽象类的子类必须实现抽象方法
}
calss Crystal extends Girl {
    job() {
        console.log('action')
    }
}
calss Taylor extends Girl {
    job() {
        console.log('Saw you')
    }
}

配置文件——tsconfig.json

在文件根目录下终端使用指令tsc -init,就会生成默认配置文件tsconfig.json

tsc -init

ts-node 指令等于 tsc demo.ts 加 node demo.js

但是ts-node遵循配置文件,tsc demo.ts不会执行默认配置文件

直接执行tsc就会执行默认配置文件

默认会将所有ts文件都转化为js文件,如果按需转化,则可以在配置文件中加入include项,数组中加入要转化的文件名即可,也可以用exclude排除不转化的文件

"include": ["demo.ts", "demo2.ts"]
//"exclude": ["demo3.ts"]

与include共呢个相似的一个项:files,用法也几乎一样

在配置文件的compilerOptions中常用项的功能了解:

"compilerOptions": {
    "removeComments": true  //删除注释
    "strict": true  //严格按照ts的书写和语法要求,就是ts的严格模式
    "noImplicitAny": true  //如果一个变量没有类型注释,则类型推断为any,此项打开后不用再为该变量写类型注释也不会报错。"noImplicitAny"仅在"strict"不生效情况下可以使用
    "strictNullChecks": false  //如果为true,ts文件中不允许出现null。仅在"strict"不生效情况下可以使用

    "outDir": "./build"  //指定ts转化生成的js文件的存放位置
    "rootDir": "./src"  //要转化的ts文件的位置
    "sourceMap": true  //生成js文件同时生成一个.map文件,里面有生成文件与源文件的一些信息
    "noUnusedLocals": true  //打开的话如果检测到有未使用的变量则会在打包时报错提示
    "noUnusedParameters": true  //打开的话如果检测到有未使用的方法则会在打包时报错提示

}

联合类型与类型保护/类型守护

interface Waiter {
    anjiao: boolean;
    say: () => {}
}
interface Teacher {
    anjiao: boolean;
    skill: () => {}
}

function judgeWho(a: Waiter | Teacher) {
    //传入参数是多种就是联合类型
    //因为不确定a是否有say方法,直接执行a.say()会报错
    //方法一:断言
    if(a.anjiao) {
        (a as Teacher).skill()
    } else {
        (a as Waiter).say()
    }
}

function judgeWho2(a: Waiter | Teacher) {
    //方法二
    if('skill' in a) {
        a.skill()
    } else {
        a.say()
    }
}

//方法三
function add(a: number | string, b: number | string) {
    if(typeof a === 'number' && typeof b === 'number') {
     return `${a}${b}`
    }
    return 0
}


//方法四
class numObj {
    count: number
}
//instance只能用在类上,不然会报错
function addObj(a: object | numObj, b: object | numObj){
    if(a instanceof numObj && b instanceof numObj) {
        return a.count + b.count
    }
    return 0
}

枚举

enum Status {
    a,
    b,
    c
}
//枚举默认给成员从0开始排序
console.log(Status.a)  //0
console.log(Status.b)  //1
console.log(Status.c)  //2
//也可以反向查询
console.log(Status[1])  //b

//枚举可以自定义排序起始编号
enum Status {
    a = 5,
    b,
    c
}
console.log(Status.a)  //5
console.log(Status.b)  //6
console.log(Status.c)  //7

泛型

//泛型在真正使用时才确定其类型
function join<T>(a: T, b:T) {
    return `${a}${b}`
}
join<number>(1, 2)

//泛型中数组的使用
function myFun<T>(params: T[]) {  //还有一种写法:function myFun<T>(params: Array<T>)
    return params;
}
myFun<string>(['abc', '123'])

//多个泛型的使用情况
function join<T, P>(a: T, b: P) {
    return `${a}${b}`
}
join<string, number>('abc', 123)
//泛型支持类型推断,所以这里也可以写成join('abc', 123)
//泛型的类型推断不利于代码理解,不建议使用

类中使用泛型

class SelectMark<T extends number | string> {  //泛型约束,泛型的类型只能是二者之一
    constructor(private marks: T[]) {}
    getMark(index: number): T {
        return this.marks[index]
    }
}
const selectMakr = new SelectMark<string>(['a','b','c'])
console.log(selsecMark.getMark(1))

泛型的继承

interface Mark {
    name: string
}

class SelectMark<T extends Mark> {
    constructor(private marks: T[]) {}
    getMark(index: number): string {
        return this.marks[index].name
    }
}
const selectMark = new SelectMark([
    {name: 'taylor'},
    {name: 'crystal'},
    {name: 'cutaoki'}
])
console.log(selectMark.getMark(1))

命名空间,减少全局变量污染,实现基本的封装

namespace Home{
    class Header {
        constructor() {
            const elem = document.createElement('div')
            elem.innerText = 'This is Header'
            document.body.appendChild(elem)
        }
    }

    class Content {
        constructor() {
            const elem = document.createElement('div')
            elem.innerText = 'This is Content'
            document.body.appendChild(elem)
        }
    }

    class Footer {
        constructor() {
            const elem = document.createElement('div')
            elem.innerText = 'This is Footer'
            document.body.appendChild(elem)
        }
    }

    export class page{
        constructor() {
            new Header()
            new Content()
            new Footer()
        }
    }
}

子命名空间

namespace Components{
    export namespace SubComponents{
     export class Test{}
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值