英文:
Flow Type: How to create an instance of an exact type from a class
问题
我有以下类型和类:
export type ProductType = {
id: number,
name: string,
slug: string,
tooltip: string,
properties?: string[]
};
class Product {
id: number;
name: string;
slug: string;
tooltip: string;
properties?: string[];
constructor(props: $Shape<ProductType>) {
this.id = props.id;
this.name = props.name || '';
this.slug = props.slug || '';
this.tooltip = props.tooltip || '';
this.properties = props.properties || [];
}
}
我希望能够像这样做:
const product: ProductType = new Product({ name: 'test' });
但Flow报错如下:
无法将 `new Product()` 赋值给 `product`,因为不精确的 `Product` [1] 与精确的 `ProductType` 不兼容
因此,我想知道是否有任何方法可以从类构造函数返回一个精确/冻结/封闭的对象,或者是否可能实现这一点,如果不可能的话,我还有哪些其他选择。
英文:
I have the following type and class:
export type ProductType = {|
id: number,
name: string,
slug: string,
tooltip: string,
properties?: string[]
|};
class Product {
id: number,
name: string,
slug: string,
tooltip: string,
properties?: string[]
constructor(props: $Shape<ProductType>) {
this.id = props.id;
this.name = props.name || '';
this.slug = props.slug || '';
this.tooltip = props.tooltip || '';
this.properties = props.properties || [];
}
}
and I'd like to be able to do something like this:
const product: ProductType = new Product({ name: 'test' });
but flows complain saying the following:
Cannot assign `new Product()` to `product` because inexact `Product` [1] is incompatible with exact `ProductType`
so I'd like to know if there is any way to return an exact/freeze/seal object from the class constructor or if this is even possible and if not what other alternatives I have.
答案1
得分: 3
抱歉,类实例是不精确的。这里有一个示例:
class Foo {
foo: string;
constructor() {
this.foo = 'foo';
}
}
class Bar extends Foo {
bar: string;
constructor() {
super();
this.bar = 'bar';
}
}
type JustFoo = {| foo: string |};
const x: Foo = new Bar();
// 预期的错误 - 如果 Flow 允许这样做,确切的类型将是不准确的!
const y: JustFoo = x;
const z: JustFoo = { foo: "foo" };
在这种情况下,Bar
扩展了 Foo
并添加了一个额外的属性。因为类是按名义类型化的,所以 Bar
是 Foo
的子类型。因此,Foo
不能成为 {| foo: string |}
的子类型,否则会破坏类型系统。
创建一个精确对象的推荐方式是像我在这个示例中为 z
所做的那样,只需编写一个对象字面量。
英文:
Unfortunately, class instances are inexact. Here's an illustration:
class Foo {
foo: string;
constructor() {
this.foo = 'foo';
}
}
class Bar extends Foo {
bar: string;
constructor() {
super();
this.bar = 'bar';
}
}
type JustFoo = {| foo: string |};
const x: Foo = new Bar();
// Expected error -- if Flow allowed this, the exact type would be a lie!
const y: JustFoo = x;
const z: JustFoo = { foo: "foo" };
In this case, Bar
extends Foo
and adds an additional property. Because classes are nominally typed, Bar
is a subtype of Foo
. Therefore, Foo
cannot be a subtype of {| foo: string |}
without breaking the type system.
The recommended way to create an exact object is to just write an object literal, like I did for z
in this example.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论