export declare type ReceiptEnum = { Action: { actions: Action[]; // Action is a type too. Consider it as a string for the ex. gasPrice: string; inputDataIds: string[]; outputDataReceivers: string[]; signerId: string; signerPublicKey: string; }; } | { Data: { data: string; dataId: string; }; };Tengo este código anterior y quiero lanzar algo que será del tipo
const data : ReceiptEnum['Action'] = {}; // This doesn't work ¿Cómo haría eso en TS? Hacer esto actualmente arroja un error Property 'Action' does not exist on type 'ReceiptEnum'
No se puede hacer referencia a una propiedad de una unión de esa manera. Deberá declarar tipos separados para ellos:
interface ReceiptAction { actions: Action[]; gasPrice: string; inputDataIds: string[]; outputDataReceivers: string[]; signerId: string; signerPublicKey: string; } interface ReceiptData { data: string; dataId: string; } export declare type ReceiptEnum = { Action: ReceiptAction } | { Data: ReceiptAction; }; Entonces puede referirse directamente a ReceiptAction .
TypeScript, en lo que a mí respecta, no admite enumeraciones que contengan datos similares a estructuras (a diferencia de rust, por ejemplo) que parece que está tratando de recrear aquí. ver los comentarios
No se puede indexar el tipo de esa manera. TypeScript no tiene 1 ninguna información sobre las variantes de unión hasta que compruebe cuál es. Es por eso que no puedes indexarlo. E incluso si pudiera, el tipo resultante no sería asignable a ReceiptEnum .
Pero aún puede construir su tipo existente de la siguiente manera:
const data: ReceiptEnum = { Action: { gasPrice: "", inputDataIds: [], outputDataReceivers: [], signerId: "", signerPublicKey: "", }, }; Pero normalmente uso un campo separado (por ejemplo, type ) para distinguir las variantes de unión. Es un patrón bastante común en TypeScript hasta donde yo sé.
export enum ReceiptType { Action, Data, } export interface ActionReceipt { type: ReceiptType.Action, actions: Action[]; gasPrice: string; inputDataIds: string[]; outputDataReceivers: string[]; signerId: string; signerPublicKey: string; } export interface DataReceipt { type: ReceiptType.Data, data: string; dataId: string; } export type Receipt = ActionReceipt | DataReceipt; // Usage: const receipt: Receipt = { type: ReceiptType.Action, actions: [], gasPrice: "", inputDataIds: [], outputDataReceivers: [], signerId: "", signerPublicKey: "", }; processReceipt(receipt); function processReceipt(receipt: Receipt) { if (receipt.type == ReceiptType.Action) { return processActionReceipt(receipt); } throw new Error(`processing of receipt type ${receipt.type} not implemented`); } function processActionReceipt(receipt: ActionReceipt) {}Bueno, tiene mucho sentido que TS te esté lanzando ese error. Está declarando que data son del tipo Action a pesar de que Action tiene una cantidad de campos obligatorios that don't exist in the empty object that is assigned to los datos.
Si el objetivo aquí es fingir que data ya son un tipo de Action válido, entonces lo que queremos hacer es algo como esto:
const data = {} as ReceiptEnum['Action']; Sin embargo, lo que le recomiendo que haga en lugar de esto es tener todos los campos listos para funcionar con anticipación y luego crear la Action sin pretender que data ya contienen los campos que esperamos que contengan. Así que tal vez algo como esto en su lugar:
const actions = alreadyPreparedActions; const gasPrice = '$5.00'; const inputDataIds = ['a', 'b', 'c']; const outputDataReceivers = ['d', 'e', 'f']; const signerId = 'super signer!'; const signerPublicKey = 'ghi'; const data: ReceiptEnum['Action'] = { actions, gasPrice, inputDataIds, outputDataReceivers, signerId, signerPublicKey, };