TypeScript: как «изменить» тип параметра метода внутри метода? - PullRequest
0 голосов
/ 28 января 2019

У меня есть счет, который может находиться в состоянии Новый / Счет-фактура.У меня есть метод doInvoicing, который принимает новый счет-фактуру и возвращает счет-фактуру.Но я не могу изменить состояние счета в моем методе, потому что он связан с новым состоянием.

В настоящее время я могу думать только о преобразовании входного счета в Invoiced.Тем не менее, это оставляет дыру в проверке типов, так как не проверяет, что я установил состояние счета-фактуры в Invoiced.Я думаю, что операция, необходимая для этого, должна объединить шаги приведения / установки значения (если это возможно).

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
}

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Я нашел несколько неплохое решение, которое позволяет избежать копирования.Инкапсулируйте изменение в методе "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 или ни один из общих параметров.

0 голосов
/ 28 января 2019

При том, как вы его настроили, я не вижу способа сделать это без создания нового объекта счета-фактуры (или, конечно, фальсификации с утверждениями типа или any):

return {...invoice, state: InvoiceState.Invoiced};

Обратите внимание, что распространение делает только поверхностную копию, которая кажется достаточной, но ...

...