TS 学习笔记

TS开发环境搭建

  1. 安装node.js;
  2. 使用npm 全局安装 ts: npm i -g typescript ;
  3. 创建一个ts文件,编辑好之后,使用tsc命令对文件进行编译:tsc xxx.ts,会生成同名的js文件。
    在这里插入图片描述

TS基本类型

  • 类型声明:
  1. 通过类型声明指定TS中变量(形参、返回值)的类型,当为变量赋值时,TS编译器会自动检查变量是否符合定义的类型。
  2. 语法:
	let 变量:类型;
	let 变量:类型 = 值;
	function fn(参数: 类型, 参数:类型): 返回值类型 {
		...
	}

在这里插入图片描述

  • 自动类型判断:
  1. TS有自动判断类型的机制,定义变量时同时赋值而没有定义类型,那么TS会自动判断类型。
  • 类型:
    在这里插入图片描述
/* 
1. 字面量: 限制变量的值就是其本身
*/
let a: 10;
a = 11; // 修改会报错,a只能是10

// 可以使用 | 来设置多个类型
let b: "male" | "female";

b = "male";
b = "female";

/* 
2. any: 表示任意类型,相当于针对该变量关闭了ts的类型检测,不建议使用
*/
let d: any;  // let d; 不指定类型,会默认为any类型
d = 10;
d = 'hello';
d = true;

/*
3. unknown 表示任意类型的值
*/

let e: unknown;
e = 10;
e = "abc";
e = true;

// unknown 和 any 的区别:unknown 相当于类型安全的any,不会影响其他变量的类型校验。
let s: string;

// d是any类型,并且d=true,但是s是string。
// 将d赋值给s是并没有报错,相当于不仅any类型的d关闭了类型校验,被赋值的s也被关闭了。
s = d;  

// 将unknown类型的e赋值给s,会报错:不能将unknown类型赋值给string。
s = e;

// 类型断言,已经明确知道e是字符串,为了不让编译器报错,可以使用类型断言。
e = "abc";
s = e as string;
s = <string>e;


/*
4. void 和 never 一般用于指定函数的返回值
*/

// void 用来表示空,表示没有返回值或返回值为undefined、null
function fn(): void {
    // 如果设置了返回值会报错
    return 123
    // 以下三种情况不会报错
    return undefined
    return null
    return
}

// never 表示没有返回值
function fn1(): never {
    // 如果设置了返回值会报错
    return 123
    // 以下三种情况不会报错
    return undefined
    return null
    return
}

/*
5. object 表示一个js对象
*/
let f: object;
f = {};
f = function () {

};

// {} 用于指定对象中可以包含那些属性
// 语法: {属性1: 属性值, 属性2:属性值}
// 在属性名后面加 ? 代表属性是可选的
let g: {name: string, age?: number};
g = {name: '孙悟空', age: 18};

// 如果要表示name属性必须有,其他属性可有有无,则可以通过
// [propName: string]: any 表示任意类型的属性
let h: {name: string, [propNmae: string]: any};
h = {name: "猪八戒", age: 18, gender: "男"};

// 定义函数的结构,只能有a,b两个参数且为number,返回值也为number
let i: (a: number, b: number) => number;
i = function(n1, n2): number {
    return n1 + n2
}

 /*
6. array
*/

let l: (string|number)[]; // 数组中只能存在string 或 number
l = ["a", 1, ]

let m: Array<number|string>; // 数组中只能存在string 或 number
m = ["a", 1]

/*
7. tuple: 固定长度的数组
语法: [类型, 类型....]
*/
let n: [string, number];
n = ["a", 1];
n = ["a"]; // 个数不同也会会报错
n = [1, "a"]; // 顺序相反也会报错

/*
8. enum: 枚举
语法: [类型, 类型....]
*/
enum Gender{
    Male = 0,
    Female = 1
}

let o: {name: string, gender: Gender};

o = {
    name: "孙悟空",
    gender: Gender.Male
};

TS面向对象

通过类创建对象,类可以理解为对象的模型。

  • 定义类:
class 类名 {
	属性名: 类型;
	constructor(参数: 类型) {
		this.属性名 = 参数;
	}
	方法名() {
		...
	}
}
  • 示例:
class Person {
	// 实例属性
	name: string;
	// 类属性(静态属性,直接通过类访问,不需要创建对象)
	static age: number;
	// 只读属性,不能修改
	readonly gender: string = "famale";
	// 构造函数, 创建对象时传入name和age字段,创建不同的Person对象
	constructor(name: string, age: number) {
		// this就代表当前的实例对象,可以通过this设置当前实例的属性
		this.name = name;
		this.age = age;
	}
	// 定义方法
	sayHello() {
		console.log("hello")
	}
}

let per = new Person("小红", 18);
console.log(per.name);
console.log(Person.age);

继承

  1. 继承语法: class 子类 extends 父类 { }
  2. 子类中添加属性需要重新构造函数时,需要调用父类的构造函数,使用super()。
class Animal {
    public name: string;
    public age: number;

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }

    sayHello() {
        console.log("动物在叫。")
    }
}

// Dog 通过 extends 关键字继承父类Animal
class Dog extends Animal {

    gender: string;

    constructor(name: string, age: number, gender: string) {
        // 子类中添加属性需要重新构造函数时,需要调用父类的构造函数,使用super()
        super(name, age);
        this.gender = gender;
    }

    run() {
        console.log("狗在叫。")
    }
}

let dog = new Dog("旺财", 3, "公");
dog.run();
dog.sayHello();

抽象类、抽象方法

  1. 抽象类不能被实例化,只能被子类继承;
  2. 抽象类中可以定义抽象方法,但抽象方法不做具体实现,子类继承时必须实现具体的方法;
abstract class Animal {
    public name: string;

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

    // 抽象类中定义抽象方法,不做具体实现,子类继承时必须实现具体的方法
    abstract sayHello(): void;
}

class Dog extends Animal {

    // 子类必须实现父类的抽象方法
    sayHello() {
        console.log("旺旺旺");
    }
}

let dog = new Dog("旺财");
dog.sayHello();

// 抽象类不能实例化,只能被继承---这里会报错
let animal = new Animal("鱼");  

接口

参考
参考

接口用于定义一个规范。

  1. 检查变量类型:
interface labelValue{
    label:string;
 }
 
 // 在调用printLabel时,会根据接口的定义,检查传入的参数和类型;并且只检查那些必需属性是否存在,并且类型是否匹配。
 function printLabel(labelObj:labelValue){
     console.log( labelObj.label );
 }
 
 // 如果传入的没有传入label或类型不是string则会报错
 let myObj2={ size:10, label:"Size 10 Object" };
 printLabel(myObj2);
  1. 接口继承:
interface Shape {
    color: string;
}

// 定义新的接口,并继承Shape接口
interface Triangle extends Shape {
    sideNum: number;
}

// 声明变量遵循 Triangle 接口
let triangle = <Triangle>{};
triangle.color = "blue";
triangle.sideNum = 3;

triangle.sideNum1 = 4; // 这里会报错,遵循Triangel接口,只能定义color和sideNum

let square: Shape;
square.color = "red";
//报错
square.sideNum=4;
  1. 类接口:
// 定义接口ClockInterface,包含属性 currentTime:Date 和 方法getTime;
interface ClockInterface{
    currentTime:Date;
    getTime(d:Date);
}

// 类遵循接口 ClockInterface, 至少需要currentTime属性和实现getTime方法;
class Clock implements ClockInterface{
    currentTime:Date;
    age: number;
    
    constructor(h: number, m: number){}

    getTime(){
        console.log("123");
    }

}

let clock1=new Clock(30,40);
clock1.getTime()
  1. 接口继承类:
// 定义类 Point,包含属性x、y 和 方法log
class Point{
    x:number;
    y:number;
    constructor(){}
    log(){
       console.log('123456');
    }
}
// 接口继承一个类时,会继承类的成员但不包括其实现。
// 所以接口Point3d会继承类属性x、y和方法log,并且新增一个属性z
interface  Point3d extends Point{
    z:number;
}

// 变量遵循接口Point3d,只能包含x、y、z和log方法。
let point3d: Point3d={
    x:1,
    y:2,
    z:3,
    log(){
        console.log('7777');
    }
}
point3d.log();//7777

属性封装

  1. 提供get和set方法,在类外获取和修改属性;
  2. 类属性声明的简便方法;
class Animal {
    /*
    定义 public 属性,类内部和外部都可以访问
    定义 private 属性,当前类内部可以访问
    定义 protected 属性,当前类和子类可以访问
    
    */
    private _name: string;

    constructor(name: string) {
        this._name = name;
    }

    // 提供get方法,在类外面访问_name属性
    get name() {
        return this._name
    }

    // 提供set方法,在类外面修改_name属性
    set name(val: string) {
        // 这里可以加一些对修改name的校验
        this._name = val;
    }
}


class Dog {
    // 直接在构造函数中定义 public name,相当于先定义name属性,在constructor中赋值this.name = name;
    /*
        public name: string;
        constructor(name: string) {
            this.name = name;
        }
    */
    constructor(public name: string) {
        
    }
}

let dog = new Dog("旺旺")
console.log(dog);

泛型

在定义函数或类时,如果遇到类型不明确时就可以使用泛型。

// 1. 当函数输入值和返回值类型不确定时,可以使用泛型代表输入和返回的类型,用于限制类型。

function fn<T>(a: T) : T {
    return a;
}

// 2. 多个参数
 
function fn2<T, K>(a: T, b: K): T {
    console.log(b);
    return a;
}

// 3. 接口和泛型
interface Inter {
    length: number;
}
// 表示泛型T必须实现接口Inter,即存在length属性
function fn3<T extends Inter>(a: T): number {
    return a.length;
}

fn3("123");
fn3({length: 100});

// 4. 类

class MyClass<T>{
    name: T;
    constructor(name: T) {
        this.name = name;
    }
}
const mc = new MyClass("孙悟空"); // TS自动推断参数类型
const mc1 = new MyClass<string>("猪八戒"); // 指定泛型类型
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,让我来回答你关于 TypeScript 中 Symbol 和模块的问题。 首先,Symbol 是 TypeScript 中的一种新的基本数据类型,它可以用来创建唯一的标识符。在 TypeScript 中,Symbol 主要有两种用法: 1. 作为对象属性的键值,用来表示一个对象属性的唯一标识符。 2. 作为一个类的静态属性或方法,用来表示该类的唯一标识符。 下面是一个使用 Symbol 作为对象属性键值的示例: ```typescript const key = Symbol('myKey'); const obj = { [key]: 'value' }; console.log(obj[key]); // 输出'value' ``` 在上面的代码中,我们使用 Symbol('myKey') 创建了一个新的 Symbol,然后将该 Symbol 作为对象 obj 的属性键值,并赋值为'value'。最后,我们通过 obj[key] 的方式来访问该属性,并输出了'value'。 另外,模块是 TypeScript 中的另一个重要概念,它用来组织和管理代码。在 TypeScript 中,模块可以使用 import 和 export 命令来进行导入和导出。下面是一个使用模块的示例: ```typescript // moduleA.ts export const num = 123; // moduleB.ts import { num } from './moduleA'; console.log(num); // 输出123 ``` 在上面的代码中,我们定义了一个名为 num 的常量,并将其导出。然后,在另一个模块中,我们使用 import 命令将 num 导入,并通过 console.log 输出了它的值。 这就是关于 TypeScript 中 Symbol 和模块的简单介绍,希望能对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值