Typescript深入理解 | 青训营

103 阅读4分钟

1. TS与JS的联系和区别

  1. TypeScript是JavaScript的超集。
  2. 它对JS进行了扩展,向JS中引入了类型的概念,并添加了许多新的特性。
  3. TS代码需要通过编译器编译为JS,然后再交由JS解析器执行。
  4. TS完全兼容JS,换言之,任何的JS代码都可以直接当成TS使用。
  5. 相较于JS而言,TS拥有了静态类型,更加严格的语法,更强大的功能;TS可以在代码执行前就完成代码的检查,减小了运行时异常的出现的几率;TS代码可以编译为任意版本的JS代码,可有效解决不同JS运行环境的兼容问题;同样的功能,TS的代码量要大于JS,但由于TS的代码结构更加清晰,变量类型更加明确,在后期代码的维护中TS却远远胜于JS。

2. 基本数据类型

2.1 布尔类型

类型为布尔类型的变量的值只能是 true 或 false

 let hahaha:boolean;
 hahaha :true;
 hahaha:false;

2.2 数值类型

TypeScript和 JavaScript 一样,所有数字都是浮点数,所以只有一个number类型,而没有int或者float类型

 let num :number;
 num =1;

2.3 字符串

字符串类型中你可以使用单引号和双引号包裹内容,但是可能你使用的 tslint 规则会对引号进行检测,使用单引号还是双引号可以在 tslint 规则里配置。你还可以使用 ES6 语法——模板字符串,拼接变量和字符串更为方便。

let beauty:string;
beauty="iu"
let msg =`我是${beauty}圈外男友`
console.log(msg)

2.4 数组

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

2.5 元组

元组可以看做是数组的拓展,它表示已知元素数量和类型的数组。确切地说,是已知数组中每一个位置上的元素的类型

let tup1:[string,boolean,number]
tup1=["xhy",true,18]
console.log(tup1);

2.6 null 和 undefined

null 和 undefined 有一些共同特点,所以我们放在一起讲。说它们有共同特点,是因为在 JavaScript 中,undefined 和 null 是两个基本数据类型。在 TypeScript 中,这两者都有各自的类型即 undefined 和 null,也就是说它们既是实际的值,也是类型。

let x:undefined=undefined;
let y:null=null;
let money : number=1;

money =null;
money =undefined;

3. TypeScript中泛型的理解及其应用场景

泛型程序设计是程序设计语言的一种风格或范式。
泛型允许我们在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型在TS中,定义函数、接口或者类的时候,不预先定义好具体的类型,而在使用的时候在指定类型的一种特性

3.1 使用方式

泛型通过<> 的形式进行表述,可以声明:

  • 函数
  • 接口

3.3 泛型参数的默认类型

泛型参数的默认类型遵循以下规则:

  • 有默认类型的类型参数被认为是可选的。
  • 必选的类型参数不能在可选的类型参数后。
  • 如果类型参数有约束,类型参数的默认类型必须满足这个约束。
  • 当指定类型实参时,你只需要指定必选类型参数的类型实参。未指定的类型参数会被解析为它们的默认类型。
  • 如果指定了默认类型,且类型推断无法选择一个候选类型,那么将使用默认类型作为推断结果。
  • 一个被现有类或接口合并的类或者接口的声明可以为现有类型参数引入默认类型。
  • 一个被现有类或接口合并的类或者接口的声明可以引入新的类型参数,只要它指定了默认类型。

3.4 泛型的应用场景

//T的类型不确定,只有函数执行的时候才能确定
function fn<T>(a: T): T{
    return a;
}
// 可以直接调用具有泛型的函数
let result = fn(10); // 不指定泛型,TS可以自动对类型进行推断,T的类型是number,则返回值的类型也是number
let result2 = fn<string>('hello'); // 指定泛型
 
// 泛型可以同时指定多个
function fn2<T, K>(a: T, b: K):T{
    console.log(b);
    return a;
}
fn2<number, string>(123, 'hello');
interface Inter{
    length: number;
}
 
// 泛型的类型约束 T extends Inter 表示泛型T必须时Inter实现类(子类)
function fn3<T extends Inter>(a: T): number{
    return a.length;
}
 
// 泛型在类中的使用
class MyClass<T>{
    name: T;
    constructor(name: T) {
        this.name = name;
    }
}
const mc = new MyClass<string>('哈哈');
 
// 泛型在接口中的使用
interface IPerson<T1, T2> {
  name: T1
  age: T2
}
const p: IPerson<string,number> = {
  name: "why",
  age: 18
}

3.5 泛型约束

3.5.1 类型约束

类型约束是指使用 extends 关键字来约束泛型的类型

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

在上面的示例中,使用 extends Lengthwise 来限制泛型参数 T 必须符合 Lengthwise 接口的定义,也就是必须包含 length 属性

3.5.2 属性约束

属性约束是指使用类型参数中的属性来约束其他属性

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

在上面的示例中,使用 <T, K extends keyof T> 来定义泛型,其中 K 继承自 T 的 key,即 K 只能取 T 中定义过的属性名。 这样,在使用 getProperty 函数时,就可以保证 key 参数只能传入 T 中定义过的属性名。