Home > Mobile >  How do I get this nested type in TS
How do I get this nested type in TS

Time:07-24

export declare type ReceiptEnum = {
    Action: {
        actions: Action[];
        gasPrice: string;
        inputDataIds: string[];
        outputDataReceivers: string[];
        signerId: string;
        signerPublicKey: string;
    };
} | {
    Data: {
        data: string;
        dataId: string;
    };
};

I have this above code and I want to cast something which will be of type

const data : ReceiptEnum['Action'] = {}; // This doesn't work

How would I do that in TS? Doing this currentlt throws an error Property 'Action' does not exist on type 'ReceiptEnum'

CodePudding user response:

Well it makes a lot of sense that TS is throwing that error at you. You're declaring that data is of type Action despite Action having a number of mandatory fieldsthat don't exist in the empty object that is assigned todata`.

If the goal here is to pretend that data is already a valid Action type then what we want to do is something like this:

const data = {} as ReceiptEnum['Action'];

What I recommend you do instead of this though is have all of the fields ready to go ahead of time and then create the Action without pretending as if data already contains the fields that we expect it to contain. So maybe something like this instead:

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,
};

CodePudding user response:

You cannot refer to a property of a union like that. You will need to declare separate types for them:

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;
};

Then you can directly refer to just ReceiptAction.

CodePudding user response:

With ReceiptEnum['Action'] you are currently trying to index the type ReceiptEnum declaration and assign to it. That's impossible as far as I know. You probably meant to constrcut a constant with the variant containing action:

const data: ReceiptEnum = {
    Action: {
        gasPrice: "",
        inputDataIds: [],
        outputDataReceivers: [],
        signerId: "",
        signerPublicKey: "",
    },
};

If I may suggest something, this might be a better fit for your needs:

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;

const data: Receipt = {
    type: ReceiptType.action,
    gasPrice: "",
    inputDataIds: [],
    outputDataReceivers: [],
    signerId: "",
    signerPublicKey: "",
};
  • Related