Home > other >  How to assign an object a const type while extend it from some other type or interface in Typescript
How to assign an object a const type while extend it from some other type or interface in Typescript

Time:08-21

Consider code like this:

const obj = {
  a: {x: 1},
  b: {x: 2},
};

const bx = obj.b.x; // bx is number
const nx = obj.n.x; // error as expected

but now I want to have more certain type info about obj, so i do:

const obj = {
  a: {x: 1},
  b: {x: 2},
} as const;

const bx = obj.b.x; // changed:  bx is 2
const nx = obj.n.x; // same:     error as expected

until now everythink is ok, but now I need to restrict other team members to patch/add values to obj in specific general-shape, so:

type GeneralTypeToFollow = { [k in string]: {x: number} }

const obj: GeneralTypeToFollow = {
  a: {x: 1},
  b: {x: 2},
  
  wrong: 'wrong type', // error as expected
} as const;


const bx = obj.b.x; // changed: bx downgraded to number
const nx = obj.n.x; // changed: nx is number (no error at all)

Restriction now works, but bx and nx has lost correct types.

So the expected behavior is:

const bx = obj.b.x; // bx is 2
const nx = obj.n.x; // error

CodePudding user response:

Your only option is to have a generic function. This function can constrain the passed object to GeneralTypeToFollow and also return the the type of the object literal.

type GeneralTypeToFollow<N extends number> = { [k in string]: { x: N } }

function makeObj<
  T extends GeneralTypeToFollow<N>,
  N extends number
>(obj: T): T {
    return obj
}

const obj = makeObj({
  a: { x: 1 },
  b: { x: 2 },
});


const bx = obj.b.x; // 2
const nx = obj.n.x; // error

By using the additional generic type N to represent the numbers, we can also get rid of as const.

Playground

  • Related