(译)【TypeScript 演化史 -- 9】object 类型 和 字符串索引签名类型的点属性

做者:Marius Schulzhtml

译者:前端小智前端

来源:mariusschulz.com/git

点赞再看,养成习惯
es6


本文 GitHub:github.com/qq449245884… 上已经收录,更多往期高赞文章的分类,也整理了不少个人文档,和教程资料。欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。github

我的专栏 ES6 深刻浅出已上线,深刻ES6 ,经过案例学习掌握 ES6 中新特性一些使用技巧及原理,持续更新中,←点击可订阅。面试

系列文章以下:typescript

【TypeScript 演化史 -- 1】non-nullable 的类型数据结构

【TypeScript 演化史 -- 2】基于控制流的类型分析 和 只读属性app

【TypeScript 演化史 -- 3】标记联合类型 与 never 类型async

【TypeScript 演化史 -- 4】更多的字面量类型 与 内置类型声明

【TypeScript 演化史 -- 5】将 async/await 编译到 ES3/ES5 (外部帮助库)

【TypeScript 演化史 -- 6】对象扩展运算符和 rest 运算符及 keyof 和查找类型

【TypeScript 演化史 -- 7】映射类型和更好的字面量类型推断

【TypeScript 演化史 -- 8】字面量类型扩展 和 无类型导入

TypeScript 2.2 引入了一个新的 object 类型。它表示任何非基本类型。如下是 JS 的基本类型:

  • string
  • boolean
  • number
  • bigint
  • symbol
  • null
  • undefined

上述之外类型都被认为是非基本类型,能够用新的 object 类型表示:

// 全部基本类型
type Primitive =
  | string
  | boolean
  | number
  | bigint
  | symbol
  | null
  | undefined;

// 全部非基本类型
type NonPrimitive = object;
复制代码

使用 object 类型的类型声明

随着 TypeScript 2.2 的发布,标准库的类型声明已经更新,以使用新的 object 类型。例如,object.create()object.setprototypeof() 方法现的参数类型是 object | null

interface ObjectConstructor {

  create(o: object | null): any;

  setPrototypeOf(o: any, proto: object | null): any;

  // ...
}
复制代码

将基本类型的值做为参数传递给 Object.setPrototypeOf()Object.create() 会致使在运行时抛出类型错误。TypeScript 如今捕获这些错误并在编译时提示错误:

const proto = {};

Object.create(proto);     // OK
Object.create(null);      // OK
Object.create(undefined); // Error
Object.create(1337);      // Error
Object.create(true);      // Error
Object.create("oops");    // Error
复制代码

object 类型的另外一个用例是 ES6 引入的 WeakMap 数据结构。它的键必须是对象,不能是基本类型值:

interface WeakMap<K extends object, V> {
  delete(key: K): boolean;
  get(key: K): V | undefined;
  has(key: K): boolean;
  set(key: K, value: V): this;
}
复制代码

object vs Object vs {}

可能使人困惑的是,TypeScript定义了几个具备类似名称但表示不一样概念的类型:

  • object
  • Object
  • {}

上面已经讲过 object 类型,如今来看看 Object{}

Object 类型

TypeScript 定义了另外一个与新 object 类型几乎同名的类型,那就是 Object 类型。object (小写)表示全部非基本类型,而 Object (大写)描述全部 JS 对象共有的功能。例如,它包括 toString()hasOwnProperty() 方法。

在TypeScript附带的lib.es6.d.ts文件中,Object类型定义以下:

interface Object {
  // ...

  /** Returns a string representation of an object. */
  toString(): string;

  /** Returns a date converted to a string using the current locale. */
  toLocaleString(): string;

  /** Returns the primitive value of the specified object. */
  valueOf(): Object;

  /**
   * Determines whether an object has a property with the specified name.
   * @param v A property name.
   */
  hasOwnProperty(v: string): boolean;

  /**
   * Determines whether an object exists in another object's prototype chain.
   * @param v Another object whose prototype chain is to be checked.
   */
  isPrototypeOf(v: Object): boolean;

  /**
   * Determines whether a specified property is enumerable.
   * @param v A property name.
   */
  propertyIsEnumerable(v: string): boolean;
}
复制代码

空类型 {}

还有另外一种类型与之很是类似:{},即空类型。它描述了一个自己没有成员的对象。当我们试图访问此类对象上的任意属性时,TypeScript 会提示编译时错误

// Type {}
const obj = {};

// Error: 类型“{}”上不存在属性“prop”
obj.prop = "value";
复制代码

可是,仍然可使用在 Object 类型上定义的全部属性和方法,这些属性和方法经过JS 的原型链调用:

// Type {}
const obj = {};

// "[object Object]"
obj.toString();
复制代码

字符串索引签名类型的点属性

在 TypeScript 2.2 以前,若是想访问带有字符串索引签名的类型的任意属性,就必须使用[]符号,但不容许使用.符号访问

interface Dictionary<T> {
  [key: string]: T;
}

const portNumbers: Dictionary<number> = {};

// OK
portNumbers["http"] = 80;

// Error: Property 'http' does not exist on type 'Dictionary<number>'.
portNumbers.http = 80;
复制代码

TypeScript 2.2 取消了这个限制。如今可使用 []. 符号访问属性。在许多状况下,再也不须要像这样使人不快的变通方法:

// 笨拙的方式
(portNumbers as any).http = 80;
复制代码

请注意,类型必须定义显式字符串索引签名,以便用.符号访问对任意属性都是类型正确的。在类型使用上使用.符号访问未知属性仍然是一个错误,所以,对于如下代码,TypeScript 2.2 仍然会给出一个编译时错误:

const portNumbers = {};

// OK
portNumbers["http"] = 80;

// Error: Property 'http' does not exist on type '{}'.
portNumbers.http = 80;
复制代码

若是仔细想一想,就会发现这颇有意义:若是 TypeScript 没有为这段代码提供一个错误,那么就没有对拼写错误的属性名的保护。在 JS 中访问属性时,大多数时候将使用表示法,但也可使用括号表示法做为转义。

有了这个较松的限制,对于经常使用JS 开发的人员来讲更容易使用。若是我们要将现有的 JS 代码基础迁移到 TypeScript,这尤为有用。给定适当的字符串索引签名,在这些状况下,就会得到更少的类型错误,而且再也不须要使用类型注释注释点属性访问,这只是为了让编译器经过。


原文:

mariusschulz.com/blog/the-ob…

mariusschulz.com/blog/dotted…


交流

干货系列文章汇总以下,以为不错点个Star,欢迎 加群 互相学习。

github.com/qq449245884…

我是小智,公众号「大迁世界」做者,对前端技术保持学习爱好者。我会常常分享本身所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复福利,便可看到福利,你懂的。

clipboard.png
相关文章
相关标签/搜索