美文网首页Front End我爱编程
[FE] TypeScript关于对象字面量的属性检查

[FE] TypeScript关于对象字面量的属性检查

作者: 何幻 | 来源:发表于2018-08-07 21:53 被阅读25次

1. 背景

1.1 子类型

在类型理论中,子类型关系通过S <: T来表示,它表示ST的一个子类型。
子类型关系具有以下两个性质,

(1)自反性

S <: S

(2)传递性

S <: U    U <: T
----------------
     S <: T

对于记录类型来说,
假设有类型S = { a:A, b:B, c:C, ...}T = { x:X, y:Y, z:Z, ... }
S <: T,当且仅当,S包含的字段数多于T

这看上去有些不可思议,包含字段更多的类型S,反而“更小”,
这种性质被称为,广度子类型化(width subtyping rule)。

1.2 和类型

和类型是一种带标签的联合类型(tagged union),
通过给各分量增加标签,将它们放在了一起。

类型A与类型B的和类型,通常记为A + B,例如,

Addr = PhysicalAddr + VirtualAddr

通常通过类型标记,来区分Addr的不同分量,
例如,如果pa是一个PhysicalAddr,则inl pa是一个Addr
其中,inlinr可以看做是一个函数

inl : PysicalAddr -> PhysicalAddr + VirtualAddr
inr : VirtualAddr -> PhysicalAddr + VirtualAddr

一般的,一个类型A + B的元素,
是由标记为inlA元素,和标记为inrB元素组成的。

和类型相关的类型推导规则如下,

    a: A
------------
inl a: A + B
    b: A
------------
inr b: A + B

2. TypeScript

TypeScript中的interface和union types,
分别对应于上文提到的记录类型,与和类型

(1)记录类型
根据记录类型的广度子类型化规则,以下子类型关系成立,

{a:number, b:number} <: {a:number}
{a:number, b:number} <: {b:number}

即,包含更多字段的{a:number, b:number},具有“更小”的类型。

(2)和类型
又根据,和类型的推导规则,

 x: {a:number, b:number} 
--------------------------
x: {a:number} | {b:number}

即,如果x是类型为{a:number, b:number}的值,则它也是类型为{a:number} | {b:number}的值。

3. 问题

但实际上,以上的写法是有问题的,

type A = { a: number };
type B = { b: number };
type AB = A | B;

// Type '{ a: number; b: number; }' is not assignable to type 'A'.
// Object literal may only specify known properties, and 'b' does not exist in type 'A'.
const x: A = { a: 1, b: 1 };

function f(p: A) { }

// Argument of type '{ a: number; b: number; }' is not assignable to parameter of type 'A'.
// Object literal may only specify known properties, and 'b' does not exist in type 'A'.
f({ a: 1, b: 1 });

TypeScript这样的做法,容易使人造成困扰

因为,这样看起来,{a: number, b: number}不是{a: number}的子类型,
也不是{b: number}的子类型。

然而,如果不是子类型的话,为什么{a: number, b: number}类型的值,
可以安全的赋值给{a: number} | {b: number}呢?

const y: AB = { a: 1, b: 1 };  // OK !

TypeScript会出现这样的问题,其实源于它除了进行类型检查之外,
针对对象字面量还多做了一些检查,官网记为,Excess Property Checks

Object literals get special treatment and undergo excess property checking when assigning them to other variables, or passing them as arguments. If an object literal has any properties that the “target type” doesn’t have, you’ll get an error.

注:

(1)不采用对象字面量(Object literals)的写法是完全没有问题的

type A = { a: number };
type B = { b: number };
type AB = A | B;

const t = { a: 1, b: 1 };
const x: A = t;  // OK !

function f(p: A) { }
f(t);  // OK !

(2)在对象字面量后面使用as指定类型,就不会报错了

type A = { a: number };
type B = { b: number };
type AB = A | B;

const x: A = { a: 1, b: 1 } as A;  // OK !

function f(p: A) { }
f({ a: 1, b: 1 } as A);  // OK !

(3)字面量属性检查,会检查是否传入了过多的属性字段,我们看3个字段的情形

type A = { a: number };
type B = { b: number };
type AB = A | B;

// Type '{ a: number; b: number; c: number; }' is not assignable to type 'AB'.
// Object literal may only specify known properties, and 'c' does not exist in type 'AB'.
const x: AB = { a: 1, b: 1, c: 1 };

function f(p: A) { }

// Argument of type '{ a: number; b: number; c: number; }' is not assignable to parameter of type 'A'.
// Object literal may only specify known properties, and 'b' does not exist in type 'A'.
f({ a: 1, b: 1, c: 1 });

参考

类型和程序设计语言
Excess Property Checks
Union Types
Interfaces

相关文章

  • [FE] TypeScript关于对象字面量的属性检查

    1. 背景 1.1 子类型 在类型理论中,子类型关系通过S <: T来表示,它表示S是T的一个子类型。子类型关系具...

  • JavaScript面向对象(二)

    创建对象的方式 通过构造函数 通过字面量 构造函数创建 字面量创建 添加删除对象属性 对象属性不一定必须在定义对象...

  • 02.11 对象

    对象字面量 里面是多个属性,属性名和属性值之间用冒号连接,多个属性之间用逗号隔开 注意:1.对象字面量需要保存;2...

  • 创建对象

    字面量方法创建对象 字面量对象中的属性名+引号问题 var girlFriend = {name:"二雷","na...

  • 13.对象字面量的扩展

    对象字面量的扩展 对象属性名,方法名的简写方式 计算属性

  • 17.对象

    理解对象 创建对象 Object 实例 对象字面量 属性类型 数据属性 [[Configurable]] 表示是...

  • 创建对象的三种方式

    创建对象的三种方式 - 利用字面量创建对象 使用对象字面量创建对象: 键:相当于属性名 值:相当于属性值,可以是任...

  • 深入理解ES6 --- 对象

    对象字面量语法扩展 (1) 属性初始值简写 为对象字面量属性赋值为同名的局部变量时,不必再写: 和值,只写属性名即...

  • [JavaScript基础] 对象 包装类

    对象 属性的增、删、改、查 对象的创建方法 plainObject 对象字面量 / 对象直接量 构造函数1). ...

  • JS-对象

    1. 基础 可通过字面量定义对象,在对象内部定义属性和方法 可以通过对象.属性或者对象['属性'] 对象['方法...

网友评论

    本文标题:[FE] TypeScript关于对象字面量的属性检查

    本文链接:https://www.haomeiwen.com/subject/iaczvftx.html