阅读 200

TypeScript 递归的对象处理、类型别名

资料:递归的对象

我们来看一段代码:

let foo:any = {}; let bar = {     foo } foo.bar=bar; 复制代码

将上述代码在chrome控制台打印,如下图所示,我们会发现它是一个递归的对象,即能够无线地 foo.bar.foo.bar...... 递归的对象

当我们在编码的过程中遇到类似场景,我们期望的体验是编辑器能够一直有代码提示,但是实际上我们输入 foo. 之后 VSCode 并没有给出提示。

当遇到这类场景的时候,我们就需要用到 interface 来声明递归结构。如下:

interface Foo {     bar: {         foo: Foo     } } let foo: Foo; let bar = {     foo } foo.bar = bar; 复制代码

这个时候 VSCode 就会按照预期进行正确的代码提示,如下图: 递归代码提示

资料:object vs Object vs {}

以下代码编译结论于 TypeScript 严格模式下得出

// tsconfig.json {   "compilerOptions": {     "strictNullChecks": true, // strictNullChecks 需要设置为 true     ...   }   ... } 复制代码

首先我们来了解一下 TypeScript 中的 object 类型。

在 TypeScript 2.2 版本之前没有一个类型用于表述「非原始数据类型」,即一个值非 number、string、boolean、symbol、null 或 undefined,所以在 2.2 版本的 TypeScript 中加入了 object 类型(注意是首字母小写的 object, 而不是 Object) 那么新加入的 object 与 Object 或 {} 有什么区别呢? 带着这个疑问,我们通过官方示例代码来了解 object 的用法

declare function create(o: object | null): void; create({ prop: 0 }); // OK create(null); // OK create(42); // Error create("string"); // Error create(false); // Error create(undefined); // Error 复制代码

从上述代码就能比较直观地感受到 object 类型「非原始数据类型」的特性。

Object VS object

基于上述代码我们用 Object 类型来做一个对比:

declare function create1(o: object): void; declare function create2(o: Object): void; create1({ prop: 0 }); // OK create1(null); // Error create1(undefined); // Error create1(42); // Error create1("string"); // Error create1(false); // Error create2({ prop: 0 }); // OK create2(null); // Error create2(undefined); // Error create2(42); // Ok create2("string"); // Ok create2(false); // Ok 复制代码

从上述代码我们就能直观地感受 Object 与 object 之间的区别,即 Object 可以被推论为 number、string、boolean 这三个原始数据类型。

Object VS any (非严格模式)

由于所有类型都继承自 Object ,所以我们有时候可能会困惑于以下两种变量声明方式:

let x: any; let y: Object; x = "hello word"; x = 123; x = null; x = {}; x = undefined; x = function() {}; y = "hello word"; y = 123; y = null; // 为了进行对比,此处是非严格模式,严格模式下无法通过 y = {}; y = undefined; // 为了进行对比,此处是非严格模式,严格模式下无法通过 y = function() {}; 复制代码

上述代码能够通过编译,但是实际上它们之间是存在区别的,any 没有接口(interface)而 Object 有 Object interface,所以 any 比 Object 更加自由,我们来看下面一段代码:

let a: any; let b: Object; a.doSomething(); // OK, 编译器会信任你的用法 b.doSomething(); // Error , b 中未声明 doSomething 方法 复制代码

Object VS {}

{} 继承于 Object(所有类型都继承自 Object),但 Object 与 {} 在 TypeScript 中的用法是等价的。

类型别名

与 interface 类似的概念,类型别名。

type Person = {     name: string;     gender: string;     friend: { // 对象结构         name: string;         age: number;     } } // 这样就可以正确描述 alex 类型了 let alex: Person = {     name: 'Alex',     gender: 'male',     friend: {         name: 'Lucy',         age: 18,         // gender: 'female' // 报错     } } 复制代码

类型别名和 interface 到底有什么区别呢?

  • 类型别名可以是一个联合类型,而 interface 不行

  • 在面向对象的实践中,我们主要也是使用 interface

type Person = string | number; 复制代码

习题:关于类型别名,下面用法错误的是?

// A type Str = string; const name: Str = 'panda'; // B type Num = number; const weight: Num = 10; // C type Obj = {     name: string,     weight: number }; const animal: Obj = {     name: 'panda',     weight: 10 } // D type Obj = string | number; const animal: Obj = {     name: 'panda',     weight: 10 } 复制代码

答案:D

解析

类型别名使得我们可以对一个比较复杂的类型重命名,从而提高代码阅读性。

  • A - name 被赋值 panda,所以声明为 string 是正确的。

  • B - weight 被赋值 10,所以声明为 number 是正确的。

  • C - 变量 animal 被赋值为一个对象,本选项将 animal 声明为对象类型,且和赋值对象的结构类型相符。故正确。

  • D - 变量 animal 被赋值为一个对象,但本选项声明的联合类型中均为基本数据类型。故错误。


作者:追梦玩家
链接:https://juejin.cn/post/7028425128752971789


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐