4. ts

7 min

ts vs js

一句话总结:JavaScript 是弱类型的动态语言,而 TypeScript 是强类型的静态语言,它增强了 JS 的可维护性和开发体验。

  • TypeScript:
    • 是一种静态类型语言,支持类型检查。
    • 在编译阶段捕获类型错误,减少运行时错误。
    • 支持自定义类型、接口、枚举等。
    • 适用于大型项目,团队协作,需要高可维护性和类型安全的项目
  • JavaScript:
    • 是一种动态类型语言,变量的类型在运行时确定。
    • 没有类型检查,容易引发运行时错误。
    • 适用小型项目,快速开发,不需要严格类型检查的场景

如何定义 function 的 arguments

arguments 可以用 IArguments 来定义; 其实 IArguments 就是 ts 实现定义好的 interface

interface IArguments {
    [index: number]: any;
    length: number;
    callee: Function;
}

any vs unknown vs never vs void

ts 中按以下顺序来定义强度

  1. top type:any,unknown
    • any 赋值给别人或者被赋值,都可以
    • unknown 赋值给别人不行(自身和 any 是行的),被赋值可以,且无法读取任何属性
  2. Object 万物即对象
  3. Number String Boolean
  4. number string boolean
  5. 1 ‘str’ false
  6. bottom type: never, 无法到达的类型,type a = string | never,never 会被忽略掉 alt text

Object vs object vs {}

Object:万物即对象;

const obj1:Object = 'string' // This is invalid
const obj2:Object = 123 // This is valid
const obj3:Object = true // This is valid
const obj4:Object = [] // This is valid
const obj5:Object = {} // This is valid
const obj8:Object = function(){} // This is valid
// 报错
const obj6:Object = null // This is invalid
const obj7:Object = undefined // This is invalid

object:引用类型(除了原始类型),常用于泛型约束;

const obj3:object = { name: 'test' }; // This is valid
const obj4:object = []; // This is valid
const obj5:object = function(){} // This is valid
// 报错
const obj1:object = 'strng'; // This is invalid
const obj2:object = 123; // This is invalid

{} 可以理解为 new Object

const obj1:{} = 'string'; // This is valid;
const obj2:{} = 123; // This is valid;
const obj3:{} = true; // This is valid;
const obj4:{} = []; // This is valid;
const obj5:{} = {name:'xxn'}; // This is valid;

// 报错
obj5.age = 10  // This is invalid;

interface vs type

interface

  • 定义对象的结构,仅限对象结构
  • 支持继承 (extend)
  • 重复定义支持合并
  • 性能更优
  • interface 不可以赋值给 record;如果想要将一个 interface 赋值给另一个 record ,需要给 interface 添加索引签名;

type

  • 定义类型别名,更灵活
  • 支持交叉类型 (&)
  • 不允许重复定义
  • 性能略低
  • 可以直接赋值给 record

原因是因为 需要明确 interface 的属性后才可以赋值给 record,interface 是可以生命合并的,这一点导致了 interface 是属性不明确

interface Obj {
  name: string;
}

interface IndexObj {
  name: string;
  [key: string]: string;
}
type Obj2 = {
  name: string
}
const interfaceObj: Obj = { name: 'test' }
const interfaceIndexObj: interfaceIndexObj = { name: 'test' }
const typeObj: Obj2 = { name: 'test' }

const obj:Record<string, string> = interfaceObj; // This is invalid;
const obj2:Record<string, string> = typeObj; // This is valid;
const obj3:Record<string, string> = interfaceIndexObj; // This is valid;

介绍下泛型

让类型也可以像参数一样传递,也可以叫做动态类型,

  • react 中 const [num, setNum] = useState<number>(0) 就是泛型的一种运用
  • type A<T> = string | number | T;
  • 泛型约束 extend 关键字对泛型参数进行约束
    interface Lengthwise {
      length: number;
    }
    
    function logLength<T extends Lengthwise>(item: T): void {
        console.log(item.length);
    }
    
    logLength("Hello"); // 输出:5
    logLength([1, 2, 3]); // 输出:3
    // logLength(42); // 报错:number 没有 length 属性

泛型 vs 联合类型: 泛型是动态的,可以在使用时具体指定,联合类型是静态的,表示固定的类型集合

泛型的局限性

  • 运行时会擦除,无法在运行时获取类型信息
  • 不能用于定义静态成员
  • 不能直接用于创建实例??

枚举 (enum) vs 常量枚举 (const enum)

  • 枚举:在编译后的 JavaScript 中会生成一个对象,用于存储枚举的映射关系。

  • 常量枚举:在编译后的 JavaScript 中会被直接内联,不会生成额外的对象。

枚举

  • 编译结果是对象
  • 性能略低,运行时有额外开销
  • 如果需要运行时访问枚举值,推荐使用
  • 支持动态访问

常量枚举

  • 编译后直接内联
  • 性能较高,无运行时开销
  • 如果只需要编译时使用枚举值,推荐使用
  • 不支持动态访问

类型守卫是什么

一种在运行时检查变量类型的技术,typeof, instanceOf, 自定义 is, in

const vs readonly

const

  • 用于定义常量
  • 变量不能重新赋值

readonly

  • 用于类属性或接口字段
  • 属性不能被修改
  • 仅在 ts 中检查

ts 中 declare 是什么

简单理解为:这个东西不是我写的,但是我知道

只负责告知编译器,声明一个东西,编译后不产生实际代码

ts 映射文件是什么

当你编译 .ts 文件时,TypeScript 可以生成一个 .js.map 文件。是一个用于调试的工具,它在编译后将 JavaScript 代码与原始 TypeScript 源码对应起来,使开发者能够在浏览器中调试 TypeScript,而不是编译后的 JavaScript。

在 tsconfg 中的 compilerOptions 的 sourceMap 来打开

ts 装饰器是什么

是一种特殊的语法,用于对类、方法、属性、参数等进行注解和扩展。它本质上是一个函数,能够在编译时(而非运行时)修改或增强目标对象的行为。

ts implement 是什么

你如何用 TypeScript 限制某个类必须实现某种结构?

答:使用 interface + implements

元组 vs 数组

元组越界之后将会以联合类型推断