typescript

数组

必须要声明数组类型

let arrOfNumbers : number[] =[1,2,3]  # number 数组类型
arrOfNumbers.push(2)

泛型数组

let list: Array<number> = [1, 2, 3];

元组

let x: [string, number];
、/ Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error

枚举

enum类型是对JavaScript标准数据类型的一个补充。使用枚举类型可以为一组数值赋予友好的名字

enum Color {Red, Green, Blue}
let c: Color = Color.Green;
let e: Color = Color[0]  //等同于上方

默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从1开始编号:

enum Color {Red = 1, Green, Blue} //逐渐变大
let c: Color = Color.Green; // 输出 2
let d: Color = Color.Blue;// 输出 3

全部都采用手动赋值:

enum Color {Red = 1, Green = 2, Blue = 4,Yellow}
let c: Color = Color.Green; // 输出 2
let d: Color = Color.Blue;// 输出 4
let e: Color = Color.Yellow // 输出 5
enum Color {Red = 'red', Green='green', Blue='blue'} 
// 如果枚举手动赋值的为字符串 那么必须全部赋值否则报错

常量枚举

提升性能 并不是所有枚举都能是常量枚举

const = enum Color {Red = 'red', Green='green', Blue='blue'} 

interface接口

duck typing(鸭子类型)

对对象形状的

对类进行限制

interface Person {
    readonly id : number  # 只读
    name : string
    age? : number  # 可写可不写
}
let user2:Person = {   
    id : 1,
    name :"yyc",
    age:20
}
    user2.id=3  # 报错

继承

interface Person1 {
    readonly id : number  // 只读
    name : string
    age? : number  // 可写可不写
}
interface Person2 extend Person2 {
    addr :string
}

函数

function add(a:number,b:number,c?:number) :number {  # 限制函数的参数必须是 numbeer类型 返回值必须是number类型   c 填也可不填
    return a+b
}

function add(a:number,b:number,c?:number,e:number) :number { #报错 不能再?后再+变量
    return a+b
}
interface Person {
  (x:number,y:number) => number = add
}
let add2 :Person = add

箭头函数

let fun12 = (data1:number, data2:number):boolean=> {return data1>data2};

类型推论 联合类型

let age = 18
age = "18" # 报错 ts已经将他推断为number类型 不能将他修改为string类型
let numberOrstring : string | number  # 这个变量可以是string类型也可以是number类型
   # 可在函数中使用

获取变量长度

numberOrstring.toString.length
numberOrstring.length # 报错 不能直接使用length
function add3(a:number,b:number|string) :number {
    if(typeof b ==="number"){  
        return a+b
    }
    return b.length
	# 在这里 我们已经判断了b的类型 就不用再使用tostring转换 来求b的长度了
}

public

在TypeScript里,成员都默认为public 可写可不写

class Animal{
    public name :string
    constructor(name:string){
        this.name =name  // 相当于py的构建方法
    }
}


class Animal{
    name :string
    constructor(name:string){
        this.name =name  // 相当于py的构建方法
    }
    run() {  # 方法
        return `${this.name} is running`
    }
}
const a= new Animal("dog") //  实例化
console.log(a.run()) // 调用方法
const a= new Animal("dog") //  实例化
console.log(a.run()) // 调用方法

私有成员 private

当成员被标记成private时,它就不能在声明它的类的外部访问

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

new Animal("Cat").name;

class Animal {
    constructor(private name: string) { }
    move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

protected

protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问

class Person {
    protected name: string;
    constructor(name: string) { this.name = name; }
}

class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name)
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误

静态属性

static定义origin,因为它是所有方法都会用到的属性

每个实例想要访问这个属性的时候,都要在origin前面加上类名

class Grid {
    static origin = {x: 0, y: 0};
    calculateDistanceFromOrigin(point: {x: number; y: number;}) {
        let xDist = (point.x - Grid.origin.x);
        let yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor (public scale: number) { }
}

let grid1 = new Grid(1.0);  // 1x scale
let grid2 = new Grid(5.0);  // 5x scale

console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));

继承

class Dog extends Animal{
    bark() {
        return `${this.name} 会汪汪叫!`
    }
}

const xiaogou = new Dog("dog")

super

调用父类的方法及成员 与py相同

class Dog extends Animal{
   constructor(name:string){
        super(name)
    }
    bark() {
        return `${this.name} 会汪汪叫!`
    }
}

const xiaogou = new Dog("dog")

类和接口共用

void 是什么都不返回

接口作用是限制类的标准 (对类的形状就行描述,就是对类进行约束 某个类必须有某个方法)

使用radio对类 Car进行约束 使Car必须有switchRadio方法且返回值是None

interface Radio {
    switchRadio(trigger: boolean): void  // void 返回值为None
}

interface Battery {
    checkBatteryStatus(): void
}
interface Battery1 extends Radio{ // 继承 Radio
    checkBatteryStatus(): void
}

class Car implements Radio{  // 约束 这个类必须有 switchRadio方法
    switchRadio(trigger: boolean) {
    }
}
class Cellphone implements Battery1{  // 必须要有 switchRadio方法和checkBatteryStatus方法
    switchRadio(trigger: boolean) {
    };
    checkBatteryStatus() {
    }
}

泛型 (最难)

当我们声明一个函数使如果 不声明参数类型 那么参数类型就是any(任意类型)

下面来创建第一个使用泛型的例子:identity函数。 这个函数会返回任何传入它的值。 你可以把这个函数当成是echo命令

function identity(arg) {  // arg 此时是any类型 返回值也是
    return arg
}
let a1 = identity(1)

使用any类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。 如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。

因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了类型变量,它是一种特殊的变量,只用于表示类型而不是值。

function identity<T>(arg: T): T {
    return arg;
}

当我们定义一个泛型

T相当于类型 T是什么类型 由传入的参数取决 我们必须传入参数才能知道函数的返回值类型

如果传入的是一个number T就是number 那么参数此时就是nmber 返回值也是numer

如下:

function fun<T>(arg:T): T{
    return arg
}
let a = fun(1)

T是string U是number 返回值是一个数组[number,string ]

function fun2<T,U>(arg:[T,U]) :[U,T]{ 
    return [arg[1],arg[0]]
}

let a2 = fun(["yyc",18])

泛型约束

当我们不确定某个参数是否有某个方法 却调用参数的方法 就会报错

为此,我们定义一个接口来描述约束条件使这个传染源的参数必须拥有这个方法,否者报错

如下

function loggingIdentity<T>(arg: T): T {
    console.log(arg.length);  // Now we know it has a .length property, so no more error
    return arg;
}
let a = loggingIdentity("yyc")  
// 此时传入的参数可能是1 如果是一个就一定报错 
// 考虑到这个一点 ts官方 如果要length方法使用必须要对泛型进行约束,才能编译成js 否则就算是传入的是一个有length方法的参数 也会报错 

为了成功编译成js

必须 创建一个包含.length属性的接口,使用这个接口和extends关键字还实现约束

interface Lengthwise {
    length: number; // number length方法的返回值
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
} 

let f = loggingIdentity(["yyc",18])  // 现在就不会报错了

泛型类

class GenericNumber<T> {
    zeroValue: T; 
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();  // 实例化传入的参数必须number 类型
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

泛型接口

interface User<T, U> {
    name: U,
    age: T,
}


let user: User<number, string> ={name:'yyc',age:18}

类型命名

type StrOrNumber = string | number
let res: StrOrNumber = "12"  // res的类型可以是数字或字符串
res = 1

type Directions = 'Up' | 'Down' | 'Left'
let jtoWhere: Directions = 'Left' //  jtoWhere的值必须是 'Up' | 'Down' | 'Left' 其中之一

interface IName {
    name: string
}
type IPerson = IName & { age: number }  
let person: IPerson = {name: "yyc", age: 18} // 限制定义对象是必须n只有ame,age字段且是string numnber类型
person["addr"] = "北京" // 后续操作是可以随意增加key value

声明文件

当我们再ts中使用jquery等其他js是就会报错

如果我们 想要使用

declare var jquery: any =>any; //在首行加入 全局可使用

内置类型

Partial

少传入某些属性

interface IPerson {
    name: string,
    age: number
}

let p: IPerson = {name: "yyc", age: 18}  

type IPersonal = Partial<IPerson>
let p2: IPerson3 = {name: "yyc"}

type Iomit = omit<IPerson,age>
let p2: Iomit = {name: "yyc"}

omit

除去某些属性

interface IPerson {
    name: string,
    age: number
}

let p: IPerson = {name: "yyc", age: 18}  
type Iomit = omit<IPerson,age>
let p2: Iomit = {name: "yyc"}
posted @ 2022-03-30 11:35  Gentry-Yang  阅读(36)  评论(0编辑  收藏  举报