Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
husky-dot opened this issue Dec 25, 2019 · 0 comments

Comments

@husky-dot
Copy link
Owner

作者:Marius Schulz
译者:前端小智
来源:https://mariusschulz.com/

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

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,这尤其有用。给定适当的字符串索引签名,在这些情况下,就会获得更少的类型错误,并且不再需要使用类型注释注释点属性访问,这只是为了让编译器通过。


原文:

https://mariusschulz.com/blog/the-object-type-in-typescript

https://mariusschulz.com/blog/dotted-properties-and-string-index-signatures-in-typescript


交流

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

https://github.com/qq449245884/xiaozhi

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

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

clipboard.png

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant