如何告诉 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 语句。

那么我该如何解决这个问题?

我想避免:

在这一点上我不是 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