In this TypeScript code, also repeated below, there is a function which builds up a partial object in the application's type system from component parts. However, it doesn't work with the noted error that all the result's properties are undefined
in a way that prevents assigning anything else to them. (They're not undefined
in the hover test shown, however.)
I tried using the KeyForValue
strategy noted here but that failed with an issue that the original has when using an interface
instead of a type
. Removing the dependence on the Record
utility type removed that error but left one about how that KeyForValue type was more strict than the 'one' string picked from a constant array.
I also tried using this strategy with a variadic tuple type which also didn’t work because (readonly [...K])[0]
cannot be used to index the type that K is a keyof
.
Is there another workaround for the design limitation listed in that issue, to get rid of this error but still be able to dynamically build up an object with keys and corresponding values passed in as separate parameters?
The code at the Playground link is:
interface HornPlayer {instrumentName: 'saxophone' | 'clarinet' | 'trumpet';}
interface ChordPlayer {instrumentName: 'piano' | 'organ' | 'vibraphone';}
interface BassPlayer {instrumentName: 'double bass' | 'tuba' | 'bass guitar';}
interface DrumPlayer {kitItemCount: number;}
type Instrumentalist = HornPlayer | ChordPlayer | BassPlayer | DrumPlayer;
interface JazzQuartet {
horn: HornPlayer,
chords: ChordPlayer,
bass: BassPlayer,
drums: DrumPlayer
}
const demoFn = function (
instrumentalists : [HornPlayer, ChordPlayer, BassPlayer, DrumPlayer],
) : Partial<JazzQuartet> {
//This array is hard-coded only to make the example simpler:
const roleNamesInSameOrder = ['horn', 'chords', 'bass', 'drums'] as (keyof JazzQuartet)[];
let result : Partial<JazzQuartet> = {};
const roleNameOutsideLoop = roleNamesInSameOrder[0]; // 'horn'
//Error ts(2322): Type 'HornPlayer' is not assignable to type 'undefined':
result[roleNameOutsideLoop] = instrumentalists[0];
result['horn'] = instrumentalists[0]; //this works fine though
for (let index in roleNamesInSameOrder) {
const roleName = roleNamesInSameOrder[index];
const instrumentalist = instrumentalists[index] as (JazzQuartet[typeof roleName]);
let test = result['horn']; //HornPlayer | undefined as expected
let test2 = result[roleName]; //HornPlayer | ChordPlayer | BassPlayer | DrumPlayer | undefined as expected
//Error ts(2322): Type 'HornPlayer' is not assignable to type 'undefined':
result[roleName] = instrumentalist;
}
return result;
}