我有一个发票,状态可以是“新/已开票”。我有一个doInvoicing方法,该方法需要新发票并返回已开具发票的发票。但是由于发票绑定到新状态,所以我无法更改其状态。
目前,我只能考虑将输入发票转换为“发票”。但是,这在类型检查中留下了一个漏洞,因为它无法验证我是否将发票状态设置为“已开票”。我认为为此所需的操作必须结合强制转换/设置值的步骤(如果可能)。
doInvoicing(invoice: Invoice & { state: invoiceState.New }):
Invoice & { state: invoiceState.Invoiced } {
var invoiced = invoice as Invoice & { state: invoiceState.Invoiced };
invoiced.state = invoiceState.Invoiced; // This MUST happen, but unverified
return invoiced;
}
enum invoiceState {
New, Invoiced
}
答案 0 :(得分:2)
以您设置的方式,我看不到没有创建新的发票对象(或者,当然,使用类型断言或any
进行伪造)的方法:
return {...invoice, state: InvoiceState.Invoiced};
请注意,传播仅是浅表复制,在这里看起来就足够了,但是...
答案 1 :(得分:0)
我找到了一种可以避免复制的好的解决方案。用“ setProperty”方法封装更改:
changeProp<V extends T[K], T, K extends keyof T>(obj:
{ [P in keyof T]: T[P] }, key: K, value: V): T & { [P in K]: V } {
obj[key] = value; // The required change is not verified, but at least only 1 copy for entire program
return obj as T & { [P in K]: V };
}
这是一个问题,返回的类型仅在V方面受V类型限制,而在传入的值方面不受限制。尽管如此,它可以用显式的泛型参数声明:
var invoiced: InvoicedInvoice = this.changeProp<invoiceState.Invoiced, Invoice, "state">(invoice, "state", invoiceState.Invoiced);
现在的问题是必须声明所有通用参数,而不仅是V。最好只声明V或不声明任何通用参数。