Search code examples
typescriptnamedtuplekeyofnameof

How to access name of named tuple in Typescript


I want to access the name from a named tuple to use within one of my functions. Is there a way to access the name only, similar to how you can access the type only by using the index of the tuple element.

type NamedThing = [emailId: string, anotherField: number]

// like you access the type here
type TypeOfFirst = NamedThing['0']

// how can I access the name here
const NameOfFirst = NamedThing['0']['__name__'] // Error on the __name__ accessor

I understand that this can be done in python using the way I described above. Here is an answer that shows that. How can I do this in Typescript?


Solution

  • Typescript exists to generate Javascript runtime after all. For this reason, some things are not possible if Javascript itself does not support it.

    If you were to compile following code:

    type NamedThing = [
        emailId: string, anotherField: number
    ]
    
    type NamedThing2 = {
        emailId: string; anotherField: number;
    }
    
    export const nTuple:NamedThing = ["email", 123]
    export const nStruct:NamedThing2 = { emailId : "email", anotherField : 123 }
    

    It becomes:

    exports.nTuple = ["email", 123];
    exports.nStruct = { emailId: "email", anotherField: 123 };
    

    Notice there is no way of knowing emailId and anotherField from nTuple. Because Javascript has no named tuple in the first place. No actual data type is translated into js.

    If you were to implement named tuple similar to that from Python, you have to do it manually, such as:

    function toTuple(obj:{[name:string]:any}) {
        return Object
            .keys(obj)
            .map(key=>obj[key])
    }
    
    function getByIndex(obj:{[name:string]:any}, index:number) {
        const key = Object
            .keys(obj)[index]
    
        return obj[key]
    }
    
    const nStruct = { emailId : "email", anotherField : 123 } // not actually named tuple.
    
    const email = nStruct["emailId"] // as if it's named tuple.
    const aField = getByIndex(nStruct, 1) // as if it's named tuple.
    const actualTuple = toTuple(nStruct) // ["email",  123]