如何告诉 flowtype 关于扩展部分选项对象,以便它在某个点完成
How to tell flowtype about extending a partial options object, so it will be complete at a certain point
一个非常简单的用例,你们中的大多数人都会从您的项目中了解到。
你有一个实用程序 class/function 或类似的东西:
type Options = {
foo?: string
};
class Something {
static get defaultOptions(): Options {
return {
foo: "bar"
};
}
options: Options;
constructor(options: Options) {
this.options = Object.assign({}, options, Something.defaultOptions);
}
toString(): string {
return `some thing: ${this.options.foo}`;
}
}
这只是一个具有最低复杂性的示例,但您明白了 - 在 toString 方法中我可以肯定,options.foo 可用并且将是一个字符串。
但是流程抱怨,因为它表现得好像它足够聪明,可以理解调用堆栈,但事实并非如此,它没有考虑 Object.assign 语句。
那么我该如何解决这个问题?
我想避免:
- 为每个选项添加 getter 方法。
- 添加第二个完整且具体的类型,用作 属性
的提示
在这一点上我不是 flowtype 的忠实粉丝:-/
更新
所以在那个例子中,流程会抛出这样的东西:
Cannot coerce this.options.foo to string because undefined [1] should not be coerced.
[1] 13│ foo?: string,
:
47│ }
48│
49│ get toString(): string {
50│ return `some thing: ${this.options.foo}`;
51│ }
52│
更新
看看已接受的答案,这就是要走的路。
--
成功做到了!
工作示例
type Options = {
foo?: string
};
class Something {
static get defaultOptions(): Object {
return {
foo: "bar"
};
}
options: typeof Something.defaultOptions;
constructor(options: Options) {
this.options = Object.assign({}, options, Something.defaultOptions);
}
toString(): string {
return `some thing: ${this.options.foo}`;
}
}
这确实让我的代码变得流畅,但我现在很高兴。
您可以使用 $Shape
实用程序类型。工作原理示例:
type Person = {
name: string,
age: number
};
type PersonShape = $Shape<Person>;
现在,PersonShape
相当于此对象类型:
type PersonShape = {
name?: string,
age?: number
};
在你的例子中,不要让 Options
有一个可选的 属性,只需在唯一需要可选属性的地方使用 $Shape
。它看起来像这样:
type Options = {
foo: string
};
class Something {
static get defaultOptions(): $Shape<Options> {
return {
foo: "bar"
};
}
options: Options;
constructor(options: $Shape<Options>) {
this.options = Object.assign({}, options, Something.defaultOptions);
}
toString(): string {
return `some thing: ${this.options.foo}`;
}
}
const thing = new Something({})
这里是 link 到 flow.org/try。
一个非常简单的用例,你们中的大多数人都会从您的项目中了解到。
你有一个实用程序 class/function 或类似的东西:
type Options = {
foo?: string
};
class Something {
static get defaultOptions(): Options {
return {
foo: "bar"
};
}
options: Options;
constructor(options: Options) {
this.options = Object.assign({}, options, Something.defaultOptions);
}
toString(): string {
return `some thing: ${this.options.foo}`;
}
}
这只是一个具有最低复杂性的示例,但您明白了 - 在 toString 方法中我可以肯定,options.foo 可用并且将是一个字符串。
但是流程抱怨,因为它表现得好像它足够聪明,可以理解调用堆栈,但事实并非如此,它没有考虑 Object.assign 语句。
那么我该如何解决这个问题?
我想避免:
- 为每个选项添加 getter 方法。
- 添加第二个完整且具体的类型,用作 属性 的提示
在这一点上我不是 flowtype 的忠实粉丝:-/
更新
所以在那个例子中,流程会抛出这样的东西:
Cannot coerce this.options.foo to string because undefined [1] should not be coerced.
[1] 13│ foo?: string,
:
47│ }
48│
49│ get toString(): string {
50│ return `some thing: ${this.options.foo}`;
51│ }
52│
更新
看看已接受的答案,这就是要走的路。
--
成功做到了!
工作示例
type Options = {
foo?: string
};
class Something {
static get defaultOptions(): Object {
return {
foo: "bar"
};
}
options: typeof Something.defaultOptions;
constructor(options: Options) {
this.options = Object.assign({}, options, Something.defaultOptions);
}
toString(): string {
return `some thing: ${this.options.foo}`;
}
}
这确实让我的代码变得流畅,但我现在很高兴。
您可以使用 $Shape
实用程序类型。工作原理示例:
type Person = {
name: string,
age: number
};
type PersonShape = $Shape<Person>;
现在,PersonShape
相当于此对象类型:
type PersonShape = {
name?: string,
age?: number
};
在你的例子中,不要让 Options
有一个可选的 属性,只需在唯一需要可选属性的地方使用 $Shape
。它看起来像这样:
type Options = {
foo: string
};
class Something {
static get defaultOptions(): $Shape<Options> {
return {
foo: "bar"
};
}
options: Options;
constructor(options: $Shape<Options>) {
this.options = Object.assign({}, options, Something.defaultOptions);
}
toString(): string {
return `some thing: ${this.options.foo}`;
}
}
const thing = new Something({})
这里是 link 到 flow.org/try。