Home > Back-end >  How to type known dynamic keys?
How to type known dynamic keys?

Time:12-06

Why the TransformMap type has problems with this line [adEnabled ? 'userPrincipalName' : 'krbPrincipalName']: { key: 'loginName' }? For some reason it can't be inferred the key will be either userPrincipalName or krbPrincipalName.

const adEnabled = parseInt(process.env.AD_ENABLED as string, 10);

type TransformMapValues = {
    key: string;
    transform?: (group: string) => string;
};

interface LdapUserMap {
    givenName: TransformMapValues;
    sn: TransformMapValues;
    mail: TransformMapValues;
    memberOf: TransformMapValues;
}

interface OpenLdapUserMap extends LdapUserMap {
    krbPrincipalName: TransformMapValues;
}

interface ADUserMap extends LdapUserMap {
    userPrincipalName: TransformMapValues;
}

type TransformMap = OpenLdapUserMap | ADUserMap;

const transformMap: TransformMap = {
    memberOf: {
        key: 'groups',
        transform: (group: string) => group.split(',')[0].split('=')[1],
    },
    mail: { key: 'email' },
    givenName: { key: 'firstName' },
    sn: { key: 'lastName' },
    [adEnabled ? 'userPrincipalName' : 'krbPrincipalName']: { key: 'loginName' },
};

CodePudding user response:

Typescript will only infer named keys from computed keys that are string literal types. Even if the computed keyis a union of string literal types it will fallback to inferring a string index instead of a named key:

const ky = Math.random() ? "k" : "y" // ky: "k" | "y"
const ky = Math.random() ? "k" : "y"

// let x: string = { [x: string]: string; }
let x = { [ky]: "" }

Playground Link

If you use a object spread instead you will get the desired effect:

const transformMap: TransformMap = {
  memberOf: {
    key: 'groups',
    transform: (group: string) => group.split(',')[0].split('=')[1],
  },
  mail: { key: 'email' },
  givenName: { key: 'firstName' },
  sn: { key: 'lastName' },
  ...(adEnabled ? { 'userPrincipalName': { key: 'loginName' } } : { 'krbPrincipalName': { key: 'loginName' }] }),
};

Playground Link

  • Related