Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic is generalised to a string in TypeScript

Tags:

typescript

I have a generic function, which can be simplified to the example below:

type Delegate<Key extends "firstKey" | "secondKey"> = {
  key: Key;
  deleteMany: (where: { where: { [n in Key]: string } }) => Promise<unknown>;
};

const removeDuplicatesGeneric = <Key extends "firstKey" | "secondKey">(
  delegate: Delegate<Key>
) => {
  delegate.deleteMany({ where: { [delegate.key]: 'key' } });
};

As key is of the type Key, I expect it to not cause issues when passing to where. TypeScript shows me an error though:

Type '{ [x: string]: string; }' is not assignable to type '{ [n in Key]: string; }'.

Any ideas why [delegate.key] is interpreted as x: string instead of x: Key?

like image 849
Vladyslav Zavalykhatko Avatar asked Oct 17 '25 02:10

Vladyslav Zavalykhatko


1 Answers

This behavior is by design. Because string type is much wider than "firstKey" | "secondKey" you are getting an error.

In this case, it is ok to use type assertion:

type Delegate<Key extends "firstKey" | "secondKey"> = {
    key: Key;
    deleteMany: (arg: { where: Record<Key, string> }) => Promise<unknown>;
};

const record = <
    Key extends PropertyKey,
    Value
>(key: Key, value: Value) =>
    ({ [key]: value }) as Record<Key, Value>

const removeDuplicatesGeneric = <Key extends "firstKey" | "secondKey">(
    delegate: Delegate<Key>
) => {
    delegate.deleteMany({ where: record(delegate.key, 'key') });
};

Playground

like image 157
captain-yossarian Avatar answered Oct 18 '25 21:10

captain-yossarian