Reputation: 2485
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.
This is a simplified refactor of this question meant to avoid having the simplifying refactor invalidate any points of an answer posted there; you can see more of what was previously attempted in that description.
How do I get rid of this error while still dynamically building up an object?
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
}
declare function recruit<R extends keyof JazzQuartet>(roleToRecruitFor: R) : JazzQuartet[R];
const demoFn = function (
//Note: If roles are repeated here it's OK;
//the last recruit for a repeated role will be in the combo.
rolesToInclude : (keyof JazzQuartet)[],
) : Partial<JazzQuartet> {
let combo : Partial<JazzQuartet> = {};
for(let role of rolesToInclude) {
//Error ts(2322): Type 'HornPlayer | ChordPlayer | BassPlayer | DrumPlayer'
//is not assignable to type 'undefined'.
combo[role] = recruit(role);
}
return combo;
}
Upvotes: 1
Views: 47
Reputation: 9903
Try to use Pick<object, key>
type instead of Partial<object>
. This would require having a type parameter for the key, a.k.a. the "role" in the jazz quartet:
interface JazzQuartet {
horn: {
instrumentName: 'saxophone' | 'clarinet' | 'trumpet'
}
chords: {
instrumentName: 'piano' | 'organ' | 'vibraphone'
},
bass: {
instrumentName: 'double bass' | 'tuba' | 'bass guitar'
},
drums: {
kitItemCount: number
}
}
declare function recruit<R extends keyof JazzQuartet>(roleToRecruitFor: R) : JazzQuartet[R];
function combine<Role extends keyof JazzQuartet>(roles: Role[]): Pick<JazzQuartet, Role> {
const combo = {} as Pick<JazzQuartet, Role>
for (const role of roles) {
combo[role] = recruit(role)
}
return combo
}
Upvotes: 1