实现JavaScript选项对象参数模式?

Jam*_*ers 7 typescript

JavaScript中有一个通用模式,"构造函数"接受可选的选项对象.此外,该选项对象可能只包含调用者希望覆盖的选项.例如:

function Foo(options) {
  this._options = {
    foo: 'bar',
    answer: 42,
    amethod: function(){}
  };
  this._options = Object.assign(this._options, options);
}

let foo1 = new Foo();
foo2._options.foo; // 'bar'
foo1._options.answer; // 42
foo1._options.amethod(); // undefined

let foo2 = new Foo({answer: 0, amethod: function(a) { return a; }});
foo2._options.foo; // 'bar'
foo2._options.answer; // 0
foo2._options.amethod('foo'); // 'foo'
Run Code Online (Sandbox Code Playgroud)

是否可以在Typescript中实现此模式?如果是这样,怎么样?

Cod*_*gue 12

看起来好像你可以使用带有可选成员的接口,并使用已经完成的Object.assign:

interface Options {
  foo?: string;
  answer?: number,
  aMethod?: (a:string) => string;
}

class Foo {
    options: Options;
    constructor(options:Options) {
        this.options = {
            foo: 'bar',
            answer: 42,
            aMethod: function(){}
        };
        Object.assign(this.options, options);
    }
}
var foo1 = new Foo({});
foo1.options.foo; // 'bar'
foo1.options.answer; // 42
foo1.options.aMethod; // function()
var foo2 = new Foo({answer: 0, aMethod: function(a:string) { return a; } );
foo1.options.foo; // 'bar'
foo1.options.answer; // 0
foo1.options.aMethod; // function(a)
Run Code Online (Sandbox Code Playgroud)

TS游乐场示例

  • 我懂了。我试图将该方法定义为完全类型化方法,同时也是可选的。TS 对此一无所知。谢谢。 (2认同)

gom*_*osg 9

在打字稿中

让我附上一个 TS 答案。在 TS 中,您当然可以定义选项对象的类型,但从 TS 3.2 开始,您不能在函数参数中分配“部分默认值”(即,当对象的未设置属性将默认为某个值时)。

所以这是使用解构的网络爬虫功能的真实示例。您也可以使用Object.assign但为了类型安全,您必须单独定义options.

总而言之,唯一需要注意的是,您必须两次提及这些属性,这些属性将被分配一个默认值。

async downloadPageHTML(url: string, options: {
    cookies?: puppeteer.Cookie[],
    launchOpts?: LaunchOptions,
    pageLoadOpts?: Partial<puppeteer.NavigationOptions>,
    userAgent?: string
    browser?: puppeteer.Browser
} = {}) {
    let {
        pageLoadOpts = {},
        launchOpts = {},
        cookies = [],
        userAgent = getUserAgent(url)
    } = options;
    // ...
}
Run Code Online (Sandbox Code Playgroud)


Rob*_*ner 5

这是一种更具异国情调的ES6方式,用于通过分解分配而不是通过实现默认选项Object.assign()

interface Options {
  foo?: string;
  answer?: number,
  aMethod?: (a:string) => string;
}

class Foo {
    options: Options;
    constructor({
            foo = 'bar',
            answer = 42,
            aMethod = undefined
        }: Options = {}) {
        this.options = { foo, answer, aMethod };
    }
}
var foo1 = new Foo();
console.log("foo1: foo", foo1.options.foo); // 'bar'
console.log("foo1: answer", foo1.options.answer); // 42
console.log("foo1: aMethod", foo1.options.aMethod); // function()
var foo2 = new Foo({answer: 0, aMethod: (a:string) => { return a; } );
console.log("foo2: foo", foo2.options.foo); // 'bar'
console.log("foo2: answer", foo2.options.answer); // 0
console.log("foo2: aMethod", foo2.options.aMethod); // function(a)
Run Code Online (Sandbox Code Playgroud)

进一步说明:http : //simonsmith.io/destructuring-objects-as-function-parameters-in-es6/

  • 它是TypeScript。在Node执行之前,必须反编译它。也可以编译到ES5。 (4认同)