随笔 - 53  文章 - 1  评论 - 0  阅读 - 12303

TypeScript知识点

定义

TypeScript 是由微软开发的自由和开源的编程语言, 是JavaScript 的一个超集,支持 ECMAScript 6 标准。其设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。

复杂的类型声明示例

常用知识点

  • 修饰符

    • public 在TypeScript里,成员都默认为 public,我们可以自由的访问程序里定义的成员
    • private 当成员被标记成 private时,它就不能在声明它的类的外部访问
    • protected 和private类似, 但是protected成员在派生类中仍然可以访问
  • 常用类型
    stringbooleannumbernumber[]、、、、

  • type和interface区别

    • 相同点
      • 类型:对象、函数两者都适用
      • 都能通过extends进行扩展
    • 不同点
      • type能够声明别名而interface不行,type 可以用于基础类型、联合类型、元组。
      • 同名合并:interface 支持,type 不支持。
      interface User {
        name: string
        age: number
      }
      
      interface User {
        sex: string
      }
      
      /*
      User 接口为 {
        name: string
        age: number
        sex: string 
      }
      */
      
      • 计算属性:type 支持, interface 不支持。
      let div = document.createElement('div');
      type B = typeof div
      
  • 用法概览1

// 布尔类型
let isCookie:boolean = true

// 数值类型
let myMoney:number = 12

// 字符串类型
let name:string = '徐小夕'

// 数组类型, 有两种表示方式,第一种可以在元素类型后面接上[],表示由此类型元素组成的一个数组
let arr:number[] = [1,2,2]

// 数组类型, 使用数组泛型
let arr:Array<number> = [1,2,2]

// 元组类型, 允许表示一个已知元素数量和类型的数组,各元素的类型不必相同
let xi: [string, number];
// 初始化xi
xi = ['xu', 10]; // 正确
xi = [11, 'xu']; // 错误

// 枚举类型, 可以为一组数值赋予友好的名字
enum ActionType { doing, done, fail }
let action:ActionType = ActionType.done    // 1

// any, 表示任意类型, 可以绕过类型检查器对这些值进行检查
let color:any = 1
color = 'red'

// void类型, 当一个函数没有返回值时,通常会设置其返回值类型是 void
function getName(): void {
    console.log("This is my name");
}

// object类型, 表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型
let a:object;
a = {props: 1}
  • 用法概览2
// 类型断言- as or <>

// interface用于对象
interface App {
  name: string;
  color?: number;
  [propName: string]: any;
}

// interface用于函数
interface MyFunc {
  (value:string, type: number): boolean;
}

// interface用于类
interface TickInterface {
    tick();
}
class DigitalClock implements TickInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("xu xu");
    }
}

// 抽象类做为其它派生类的基类使用。它们一般不会直接被实例化。不同于接口,抽象类可以包含成员的实现细节。abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。
abstract class MyAbstract {
    constructor(public name: string) {}
    say(): void {
        console.log('say name: ' + this.name);
    }
    abstract sayBye(): void; // 必须在派生类中实现
}
class AccountingMyAbstract extends MyAbstract {
    constructor() {
        super('test'); // 在派生类的构造函数中必须调用 super()
    }
    sayBye(): void {
        console.log('test1');
    }
    getOther(): void {
        console.log('test2');
    }
}
let department: MyAbstract; // 允许创建一个对抽象类型的引用
department = new MyAbstract(); // 错误: 不能创建一个抽象类的实例
department = new AccountingMyAbstract(); // 允许对一个抽象子类进行实例化和赋值
department.say();
department.sayBye();
department.getOther(); // 错误: 方法在声明的抽象类中不存在

// 函数,在参数名旁使用 ?实现可选参数的功能,可选参数必须跟在必选参数后面
function createName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

/** 泛型 */
// 泛型-函数中直接使用
function iSay<T>(arg: T): T { // 整体使用泛型
    return arg;
}
let come = iSay<number>(123);

function iSay<T>(arg: T[]): T[] { // 局部使用泛型
    console.log(arg.length)
    return arg;
}
// 泛型-函数中定义使用
interface SayLove {
    <T>(arg: T): T
}
interface SayLoveArg<T> { // 把泛型参数当作整个接口的一个参数
    (arg: T): T
}
let mySay1:SayLove = iSay
let mySay2:SayLoveArg<number> = iSay

// 泛型-类中直接使用
class MyNumber<T> {
    year: T;
    compute: (x: T, y: T) => T;
}
let myGenericNumber = new MyNumber<number>();

// 泛型-类中定义使用-类似类型别名
interface NumberControl {
    length: number
}
class MyObject<T extends NumberControl>(arg: T):T {
    console.log(arg.length)
    return arg
}

// 交叉类型
function extend<T, U>(first: T, second: U): T & U {
   let result = {} as T & U; // <T & U>{}
    for (let id in first) {
        (<any>result)[id] = (<any>first)[id];
    }
    for (let id in second) {
        if (!result.hasOwnProperty(id)) {
            (<any>result)[id] = (<any>second)[id];
        }
    }
    return result;
}

// 联合类型
let name: string | number = 'test';

// 多态的 this类型
class MyCalculator {
    public constructor(number = 0) { }
    public add(n: number): this {
        this.value += n;
        return this;
    }
    public multiply(n: number): this {
        this.value *= n;
        return this;
    }
    // ... 其他操作 ...
}

// 索引类型查询操作符
interface Animal {
    cat: string;
    dog: string;
}
let AnimalProps: keyof Animal; // 'cat' | 'dog'

// 索引访问操作符
interface TestInterface {
    a: string,
    b: number,
    c: boolean,
    d: symbol,
    e: null,
    f: undefined,
    g: never
}
type MyType = TestInterface[keyof TestInterface]; // 通过[]索引类型访问操作符, 我们就能得到某个索引的类型

// 命名空间-主要作用是用来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。
declare namespace D3 {
    export interface Selectors {
        select: {
            (selector: string): Selection;
            (element: EventTarget): Selection;
        };
    }
    export interface Event {
        x: number;
        y: number;
    }
    export interface Base extends Selectors {
        event: Event;
    }
}
declare var d3: D3.Base;

// 使用第三方类库
npm install --save lodash @types/lodash
import * as _ from "lodash"; // 在代码中使用
_.padStart("Hello world!", 2, " ");

// 声明文件-使用未经声明的全局函数或者变量, typescript会报错, 可以添加xxx.d.ts文件, 并在里面声明所需变量, ts会自动检索到该文件并进行解析。
// global.d.ts
declare var name: string;// 1. 声明全局变量
declare function say(name: string): void;// 2. 全局函数
declare namespace myObj {// 3. 带属性的对象
    function say(s: string): string;
    let money: number;
}
interface Animal {// 4. 可重用的接口
    kind: string;
    age: number;
    weight?: number;
}
declare function findAnmiate(animal:Animal):void;

常见DEMO

/** 一、interface和type有什么区别 */
// ****相同点****
//	1. 都能声明对象
//	2. 都能通过extends进行扩展

// 通过interface声明对象结构
interface A {
  a: string;
}
// interface扩展另一个interface
interface AA extends A {
  b: number;
}
// 通过type声明对象结构
type B = {
  a: string;
};
// type扩展另一个type
type BB = B & { b: number };
// type和interface还能相互继承
type B = {
  a: string;
};
interface C extends B {
  b: number;
}
// ****不同点****
//	1. type能够声明别名而interface不行
//	2. 同名合并:interface 支持,type 不支持。
//  3. 计算属性,type 支持, interface 不支持。
type isNumberOrBool = number | boolean;
let a: isNumberOrBool = 1;
a = true;
// Bar { a, b, c }
interface Bar {
  a: string
  b: number
 }
 interface Bar {
  c: string
 }
type Keys = "firstname" | "surname";
type DudeType = {
  [key in Keys]: string
}


/** 二、函数参数是对象时,会对对象字面量做额外的属性检查,但却不会对对象引用做检查处理 */
interface O {
  a: string;
  b: number;
}
function fn(o: O) {}
const o = { a: "a", b: 1, c: 3 };
// 下面一行能通过ts检查
fn(o);
// 下面一行不通过, 提示'c' does not exist in type 'O'
fn({ a: "a", b: 1, c: 3 });

/** 三、TypeScript的类型兼容性是基于结构的而非名义的 */
interface Named {
    name: string;
}
class Person {
    name: string;
}
let p: Named;
// OK, because of structural typing
p = new Person();

/** 四、模块,namespace和declare声明文件三者导入导出的区别 */
// 模块通过import/export去导入
// namespace和declare声明则是通过三斜线指令/// <reference path="..." />的方式去导入的

/** 五、传递过程中导致this丢失,指向全局,但是并没有收到报错 */
const fn = o.do;
// 报错,提示:The 'this' context of type 'void' is not assignable to method's 'this' of type 'O'
fn();

常见问题

Q: vscode中直接运行typescript需要安装
A: npm install -D tslib @types/node 
npm install -g typescript ts-node
posted on   DJ荒野  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示