是否可以选择严格传播对象?

ysf*_*ran 6 typescript

我想知道是否有编译器选项或类似的东西可以使传播对象严格。

请参阅以下示例以了解我的意思:

interface Foo {
  a: string;
}

interface Bar {
  a: string;
  b: number;
}

const barObject: Bar = { a: "a string", b: 1 };

// should give a warning because Bar has more properties (here b) than Foo
const fooObject: Foo = { ...barObject };

// actually prints 1
console.log((fooObject as any).b); 
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?

for*_*d04 7

有趣的问题。根据本期,价差操作者的结果是为了触发超额财产检查


// barObject has more props than Foo, but spread does not trigger excess property checks
const fooObject: Foo = { ...barObject };

// b is explicit property, so checks kicks in here
const foo: Foo = { ...bar, b: 2 }
Run Code Online (Sandbox Code Playgroud)

目前 TypeScript没有确切的类型,但您可以创建一个简单的类型检查来强制执行严格的对象传播:

// returns T, if T and U match, else never
type ExactType<T, U> = T extends U ? U extends T ? T : never : never

const bar: Bar = { a: "a string", b: 1 };
const foo: Foo = { a: "foofoo" }

const fooMergeError: Foo = { ...bar as ExactType<typeof bar, Foo> }; // error
const fooMergeOK: Foo = { ...foo as ExactType<typeof foo, Foo> }; // OK
Run Code Online (Sandbox Code Playgroud)

通过辅助函数,我们可以减少一些冗余:

const enforceExactType = <E>() => <T>(t: ExactType<T, E>) => t

const fooMergeError2: Foo = { ...enforceExactType<Foo>()(bar) }; // error
Run Code Online (Sandbox Code Playgroud)

代码示例

  • @ysfaran 一项补充:对象扩展当前的行为符合整个结构类型系统/鸭子类型,其中子类型可以分配给基本类型。在普通的变量赋值中,当您初始化新的对象文字时,您只会得到多余的属性检查。例如,您可以编写“const fooObject:Foo = bar”,因为“bar”不再是新鲜的对象文字,而是“Foo”的子类型。`const fooObject: Foo = { ...bar }` 的行为类似,`bar` 不再“新鲜”/之前已经声明过。 (3认同)
  • 所以这并不简单。我宁愿不进行检查,也不愿降低代码的可读性。遗憾的是目前没有旗帜.. (2认同)