Issue
I'm trying to write a mapped type that takes a list which can contain both objects ("definitions") and strings. String values are limited to a set of strings that refer to existing hard coded definitions. The resulting type should be an object where the keys are collected from that input list;
- for list elements of type string, use that string
- for list elements of type object, use the
name
property from that object
Here is my current code:
type CustomDefinition = {
name: string;
units: string | null;
};
const predefinitions = {
'AUTOPILOT_AIRSPEED_ACQUISITION': {
name: 'AUTOPILOT_AIRSPEED_ACQUISITION',
units: 'Bool',
settable: false,
},
'AUTOPILOT_AIRSPEED_HOLD': {
name: 'AUTOPILOT_AIRSPEED_HOLD',
units: 'Bool',
settable: false,
},
'AUTOPILOT_AIRSPEED_HOLD_CURRENT': {
name: 'AUTOPILOT_AIRSPEED_HOLD_CURRENT',
units: 'Bool',
settable: false,
},
} as const;
type PredefinitionName = keyof typeof predefinitions;
type PredefinedValuesResult<SimVars extends PredefinitionName[]> = {
[VarName in SimVars[number]]: string;
};
type CustomValuesResult<SimVars extends CustomDefinition[]> = {
[VarName in SimVars[number]['name']]: string;
};
function getPredefinedValue<ReqValues extends PredefinitionName[]>(requestedValues: ReqValues): PredefinedValuesResult<ReqValues> {
return {} as PredefinedValuesResult<ReqValues>;
}
function getCustomValues<ReqValues extends CustomDefinition[]>(requestedValues: ReqValues): CustomValuesResult<ReqValues> {
return {} as CustomValuesResult<ReqValues>;
}
const predfinedValuesResult = getPredefinedValue([
'AUTOPILOT_AIRSPEED_ACQUISITION',
'AUTOPILOT_AIRSPEED_HOLD_CURRENT',
]);
const customValues = getCustomValues([
{ name: 'CUSTOM_VARIABLE', units: 'degrees' }
]);
console.log(
predfinedValuesResult.AUTOPILOT_AIRSPEED_ACQUISITION,
predfinedValuesResult.AUTOPILOT_AIRSPEED_HOLD_CURRENT,
);
console.log(
customValues.CUSTOM_VARIABLE,
);
// Un-implemented functionality:
const customAndPredefinedValues = getCustomAndPredefinedValues([
'AUTOPILOT_AIRSPEED_ACQUISITION',
{ name: 'CUSTOM_VARIABLE', units: 'degrees' }
]);
console.log(
customAndPredefinedValues.AUTOPILOT_AIRSPEED_ACQUISITION, // should autocomplete
customAndPredefinedValues.CUSTOM_VARIABLE, // should autocomplete
)
Using PredefinedValuesResult
and CustomValuesResult
alone works fine, but I want to allow the user to specify a list of both custom definitions and referring strings.
Would this be possible?
Solution
You could use a conditional type to examine the input array elements and use them directly if they are a key of predefinitions
, or to use their name
property if they are a CustomDefinition
. For example:
type Predefinitions = typeof predefinitions;
declare function getCustomAndPredefinedValues<
const T extends CustomDefinition | keyof Predefinitions>(
t: T[]
): { [K in (
T extends keyof Predefinitions ? T :
T extends CustomDefinition ? T["name"] :
never
)]: string };
Now your function behaves as desired:
const customAndPredefinedValues = getCustomAndPredefinedValues([
'AUTOPILOT_AIRSPEED_ACQUISITION',
{ name: 'CUSTOM_VARIABLE', units: 'degrees' }
]);
/* const customAndPredefinedValues: {
AUTOPILOT_AIRSPEED_ACQUISITION: string;
CUSTOM_VARIABLE: string;
} */
Answered By - jcalz
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.