#Object.entries type narrowing

10 messages · Page 1 of 1 (latest)

edgy lotus
#

i'm building static dictionaries where keys are enums, and values are functions. Then i use Object.entries to iterate on the dictionary ; when doing so, the dictionary changes from { key1: (arg: T1) => void, key2: (arg: T2) => void } to [key1 | key2, (arg: T1) => void | (arg: T2) => void][] and the constraint of key1 -> T1 + key2 -> T2 is merged in a union type, which creates type annoyance.

How to change the algorithm not to have this issue anymore?

https://www.typescriptlang.org/play/?#code/PTAEHcFNQCwQwG7QM4HsC21IDsCu7kAoHfUAaUgE9lQBvQ0UAMQHkXQBeUAcgDNVU3ADQNQAIQCCAJU48ARnABOwwgF9ChEKBIFQAYzjZQc6AAclAF1CpeoOKAAmkXgEtsLiy9RGboc5QAbVDgHGgAKCxg3AGs7dABHU1BkXDlkPUUXU09vZABKQgtKU2gABThA4NDZekYAbQpqADpWFgBdAC46UH5ULuQLTOwAc1B1esbkJskpTu6FRX7Bt1HxnmxUCwBaNwtIRUgByAduLtpjOAAvJaHVtQ0iktAAFUVDZH5FTEUmbAAeZ7aAAee2w1UmAD5ZGF-EEQl1ypUQsg6s82nlOFCBrc6m0NFooBBDFYLKhQC50KYApBMNgrN5oIN3p9vj1cNg9DkjCVFH4KnCHKBHpBCHpclYACIASQAws8zqIGuSjJM5q9magvvtfn8yBC1DVFZMWmw5jD+VUMRwoSw5AArSCcprRKjIc1Ihx5EQTV3TaRm2GWzGgW0Op0u6jugVe+6aMDoVB6WJwBJJFJpDJZLk9bCEXjszleIzp9KZEwA4Gg6oR3yIgXICERYqQLrPISwQwOamLUBRqoIi3I1Ho4MIVAuT10dRx6zYLaRSBbcAVDtJnqa7R4dBbY6gCPIdvgKJ6GDkmjs5BwXjQDZfOABAKUYy4emxNxC+BWcyKTx6XABJR9DgZARV2fZeDgPRoFDR0LBlcVFFwTkN1qTdlkOCtIBBHBqlQe1YPbMhKxwmga1sZ5Gz6F48i6Bp22eBo2jaXFRBwdDkEw7CwRoPCwwsSjWxo0A6jIl5QAAMmSZYRnokSqF8NFmLxactBgfZIG4GgF3JSlqVpCw4GzFxkBSFsZ2021sFgpo2MyQ5HFQez7BA79DN3dki2sWwI2ABB72VI4Qi8uwO2QU90DgUwRC0BcDk+aAPE0nTTFQEyXDkakhTJCKLBPYBsCURRUHAEK-ICIVm3XXl7GGFwkCMCMKpKGcYGKrLklQAIkA-Yyz1MgB+PMNzCMVsAGYSI3bMq2mCmCnVslxDjCaU5TyDFUJLTMTDCSbe0DEIrShVDGFG8amTGlldy4Mq+wO0QTtyTrICaIJhgiN4Ls1TBPVEVQCnUIA

lavish sorrelBOT
#

@edgy lotus Here's a shortened URL of your playground link! You can remove the full link from your message.

y_nk#0

Preview:```ts
// we have some enums
enum Keys {
FOO = 'foo',
BAR = 'bar',
}

// enums can be part of a definition of payloads (think amqp subscriptions)
type Payloads = {
[Keys.FOO]: { foo: string }
[Keys.BAR]: { bar: string }
'not-interested': { baz: string }
...```

glad vale
#

ah well seeing as you're already messing with the signature..

#

you could do something like this

lavish sorrelBOT
#
chris.sophos#0

Preview:ts ... entries<T extends object>( o: T ): {[K in keyof T]: [K, T[K]]}[keyof T][] } ...

glad vale
#

but it'll still run into the correspondance problem

dire adder
#

what about something like

type TransformerFn = (payload: Payloads[keyof Payloads]) => string[];

// we want to implement one transformer function per payload type
const DICT: Record<Keys, TransformerFn> = {
  [Keys.FOO]: (payload) => Object.keys(payload),
  [Keys.BAR]: (payload) => Object.keys(payload),
};
#

then val(payload) becomes a union instead of an intersection

lost ridge
#

since you're willing to override the type of Object.entries in a way that is tuned for your specific use case, you could go further and handle the iteration yourself and assert as needed. that'd be more efficient too as you'd avoid allocating those intermediate arrays

#

or go the other way and start with a tuple instead of an object (assuming the DICT encoding is not set in stone)