Typescript: Create class via constructor passing in named parameters?

时间:2017-08-04 12:55:40

标签: typescript named-parameters

I have a class where I have the constructor defined with 3 parameters which are all optional. I was hoping to be able to pass in named parameters so I don't need to pass in undefined.

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

I was hoping to create an intance of the class like so

  const recurrenceRule = new MyNewClass(month: 6)

but it didn't work and i tried

  const recurrenceRule = new MyNewClass(month = 6)

and that didn't work.

The only way i got it to work was either

  const recurrenceRule = new MyNewClass(undefined, 4)

or

  const recurrenceRule = new MyNewClass(, 4)

But it seems so messy, I was hoping to pass in named arguments and becasue they are all optional I should be able to just pass in 1 - right ?

5 个答案:

答案 0 :(得分:22)

您可以使用ES6中引入的对象解构来实现所需的行为:reference。 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();




答案 1 :(得分:2)

background-image

有关详细信息,请参阅ES6 Object Destructuring with functions

答案 2 :(得分:0)

简单参数:

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)。

答案 3 :(得分:0)

您也可以使用 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

答案 4 :(得分:0)

在某些情况下,拥有一个界面和单独的 maker 功能会更容易。 (对于未来的读者。)


interface Foo {
  x: number
  y: number
}

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

const f = newFoo({x:100})