打字稿:通过传入命名参数的构造函数创建类?
Posted
技术标签:
【中文标题】打字稿:通过传入命名参数的构造函数创建类?【英文标题】:Typescript: Create class via constructor passing in named parameters? 【发布时间】:2018-01-12 10:18:11 【问题描述】:我有一个类,其中定义了带有 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 - 对吧?
【问题讨论】:
我知道的唯一具有此功能的语言是 Swift 和 Python 你可以传入一个接口对象,但是就像@Vivick说的,这个功能在TS中是不存在的 @Vivick C# 也有很长一段时间了。 【参考方案1】:class Bar
constructor(a, b: a?: number, b?: number)
new Bar(b: 1)
有关详细信息,请参阅ES6 Object Destructuring with functions。
【讨论】:
我喜欢这个解决方案【参考方案2】:您可以使用 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 个参数调用构造函数(参见下面的 sn-p)。
有点神秘的=
是针对您创建没有任何参数的新实例的情况。首先, 被用作参数对象的默认值。然后,由于缺少
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();
【讨论】:
【参考方案3】:简单参数:
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)。
【讨论】:
【参考方案4】:您也可以使用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
。
【讨论】:
【参考方案5】:在某些情况下,拥有一个界面和单独的制造商功能会更容易。 (供未来的读者阅读。)
interface Foo
x: number
y: number
function newFoo(x=5,y=10) : Foo return x,y
const f = newFoo(x:100)
【讨论】:
以上是关于打字稿:通过传入命名参数的构造函数创建类?的主要内容,如果未能解决你的问题,请参考以下文章