簡體   English   中英

打字稿:通過傳入命名參數的構造函數創建類?

[英]Typescript: Create class via constructor passing in named parameters?

我有一個類,其中的構造函數定義了 3 個參數,這些參數都是可選的。 我希望能夠傳入命名參數,所以我不需要傳入 undefined。

constructor(year?: number,
            month?: number,
            date?: number)

我希望像這樣創建一個類的實例

  const recurrenceRule = new MyNewClass(month: 6)

但它沒有用,我試過了

  const recurrenceRule = new MyNewClass(month = 6)

那沒有用。

我讓它工作的唯一方法是

  const recurrenceRule = new MyNewClass(undefined, 4)

要么

  const recurrenceRule = new MyNewClass(, 4)

但它看起來很混亂,我希望傳入命名參數,因為它們都是可選的,我應該能夠傳入 1 - 對嗎?

您可以使用 ES6 中引入的對象解構來歸檔所需的行為: 引用 TypeScript 能夠將此功能轉譯為與 ES5 一起使用,以針對較舊的瀏覽器。 然而,從 ES6 開始,這也是完全有效的 JavaScript。

基本上,它看起來像這樣: constructor({ year, month, day})並被調用,例如,作為new Bar({ year: 2017 }) 然后你可以在構造函數中訪問year作為變量,例如分配this.year = year

比這更有趣的是使用默認值,例如

constructor({ year = new Date().getFullYear(), 
              month = new Date().getMonth(), 
              day = new Date().getDay()
            } = {})

它允許分別使用 0、1、2 或 3 個參數調用構造函數(參見下面的代碼片段)。

有點神秘的= {}用於創建沒有任何參數的新實例的情況。 首先, {}用作參數對象的默認值。 然后,由於缺少year ,因此添加默認值,然后分別添加月和日。

為了與 TypeScript 一起使用,您當然可以添加其他類型,

constructor({ year = new Date().getFullYear(),
              month = new Date().getMonth(),
              day = new Date().getDay()
}: { year?: number, month?: number, day?: number } = {}) { 
    ...                
}

雖然這看起來真的很神秘。

 class Bar { constructor({ year, month, day }) { this.year = year; this.month = month; this.day = day; } log () { console.log(`year: ${this.year}, month: ${this.month}, day: ${this.day}`); } } new Bar({ day: 2017 }).log(); class Foo { constructor({ year = new Date().getFullYear(), month = new Date().getMonth(), day = new Date().getDay() } = {}) { this.year = year; this.month = month; this.day = day; } log () { console.log(`year: ${this.year}, month: ${this.month}, day: ${this.day}`); } } console.log('with default value:'); new Foo().log(); new Foo({ day: 2 }).log(); new Foo({ day: 2, month: 8 }).log(); new Foo({ year: 2015 }).log();

class Bar {
  constructor({a, b}: {a?: number, b?: number}) {}
}

new Bar({b: 1})

有關更多信息,請參閱ES6 Object Destructuring with functions

簡單參數:

constructor (private recurrenceSettings: {year?: number, month?: number, date?: number})

private 關鍵字將參數實例化為實例變量,省去了在構造函數中實例化的需要。 如果您想實例化公共屬性,也可以是public

像這樣使用:

const recurrenceRule = new MyClass({month: 12})

或者使用解構(用法同上):

constructor({day, month, year}: {day?: number, month?: number, year?: number})

盡管上面的版本失去了對實例變量使用私有/公共快捷方式的能力(請參閱https://github.com/Microsoft/TypeScript/issues/5326 )。

您也可以使用Partial來實現相同的結果。

您將以與之前答案相同的方式實例化。

class Bar {
  year = new Date().getFullYear();
  month = new Date().getMonth();
  day = new Date().getDay();
  constructor(bar?: Partial<Bar>) {
    Object.assign(this, bar);
  }
  
  log () {
    console.log(`year: ${this.year}, month: ${this.month}, day: ${this.day}`);
  }
}

new Bar().log();
new Bar({ day: 2 }).log();
new Bar({ day: 2, month: 8 }).log();
new Bar({ year: 2015 }).log();

注意 1. Partial<Bar>可以接受任何東西,只要同名的屬性具有相同的類型。 是的,這在某種程度上違反了類型安全。 這仍然強大的原因是,如果您開始使用{鍵入對象文字,智能感知會告訴您可以初始化哪些屬性。

注意 2. Object.assign將忽略readonly屬性,因為它是 JavaScript 特定的東西,而不是 TypeScript 特定的。 這意味着雖然您不能為readonly屬性分配一個新值,但您當然可以使用Object.assign

在某些情況下,擁有一個界面和單獨的 maker 功能會更容易。 (對於未來的讀者。)


interface Foo {
  x: number
  y: number
}

function newFoo({x=5,y=10}) : Foo {return {x,y}}

const f = newFoo({x:100})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM