typescriptgenericstypespartial

Typescript: How to extract the value types of a const object and use them as keys in a new type?


I want to take a constant object, say {key1: 'value1', key2: value2'} as const, and convert its values into keys and use it in a new object with type {value1: number; value2: number}. I'd like to do this in a function, and I want the function to be typed correctly.

Below is the code that I'm trying to get to work. The error is happening when I try to cast a variable of type Partial<Blah> to Blah. Could someone explain why it's happening, and if there's a way to do what I'm trying to do? Thanks!

type BaseObject = Record<string, string>;


type ValuesAsKeys<T extends BaseObject> = {
    [K in keyof T as T[K]]: number;
};

function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T> {
  const x: Partial<ValuesAsKeys<T>> = {};
  for (const value of Object.values(arg) as Array<T[keyof T]>) {
    x[value] = 1;
  }

  // This line doesn't work
  return x as ValuesAsKeys<T>;
}

// Example use case
const obj = {key1: 'value1', key2: 'value2'} as const;
const result = useValuesAsKeys(obj); // Type of result is {value1: number; value2: number}


// Everything below here works
// Only including this because I'm contrasting this code with the code above.

type KeysAsKeys<T extends BaseObject> = {
    [K in keyof T]: number;
};

function useKeysAsKeys<T extends BaseObject>(arg: T): KeysAsKeys<T> {
    const x: Partial<KeysAsKeys<T>> = {};
  for (const value of Object.values(arg) as Array<T[keyof T]>) {
    x[value] = 1;
  }
  return x as KeysAsKeys<T>;
}

Solution

  • I'm still not sure why casting Partial<Blah> to Blah doesn't work in this scenario, but this code works and is type-safe enough for me:

    function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T> {
      const x = {} as ValuesAsKeys<T>;
      for (const value of Object.values(arg) as Array<T[keyof T]>) {
        x[value] = 1;
      }
      return x;
    }