From 058682a7b65329933da717407797bc09099ea7e4 Mon Sep 17 00:00:00 2001 From: Alina Saalfeld Date: Mon, 23 Oct 2023 15:40:00 +0200 Subject: [PATCH] play around with template literals to build better types for getFieldValueFromKeyString --- src/js/types.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/js/types.ts b/src/js/types.ts index feaae3d..a4f8a6b 100644 --- a/src/js/types.ts +++ b/src/js/types.ts @@ -97,3 +97,47 @@ export function isValidatorStepArrayArray(dependent?: Dependent): dependent is A export function isValidatorStep(dependent?: boolean | ValidatorStep): dependent is ValidatorStep { return !!dependent && Array.isArray(dependent) && !Array.isArray(dependent[0]); } + + +type ResultType = + S extends number + ? V extends Array + ? A + : undefined + : S extends `${infer First}.${infer Rest}` + ? V extends Record + ? ResultType + : never + : S extends `${infer Last}` + ? V extends Record + ? V[Last] + : undefined + : never; + +const getFieldValueFromKeyString = ( + keyString: S, values: T, +): ResultType => { + const fieldNames = String(keyString).split('.'); + let dependentValue = values; + for (const fieldName of fieldNames) { + if ((dependentValue as ObjectValue)[fieldName] === undefined) { + throw new Error('Could not find value for ' + keyString); + } + dependentValue = (dependentValue as any)[fieldName]; + } + return dependentValue as ResultType; +}; + + +// todo: the calls that result in an "unknown" type should ideally result in "undefined" instead +// todo: need to test if the calls resulting in undefined actually return undefined; if they error, type them never +const t = getFieldValueFromKeyString('test.1.str', {test: [{str: 'yay!'}]}); // string +const t2 = getFieldValueFromKeyString(0, ['3', '2']); // string +const t3 = getFieldValueFromKeyString('0', ['3', '2']); // string +const t4 = getFieldValueFromKeyString('test.1', {test: [{str: 'yay!'}]}); // {str: string} + +const b = getFieldValueFromKeyString('test.1.str.5', {test: [{str: 'yay!'}]}); // undefined +const b2 = getFieldValueFromKeyString('test.1.strrrrrr', {test: [{str: 'yay!'}]}); // unknown :( +const b3 = getFieldValueFromKeyString('test.1.str.sss', {test: [{str: 'yay!'}]}); // undefined +const b5 = getFieldValueFromKeyString('02', ['3', '2']); // unknown :( +const b6 = getFieldValueFromKeyString(1, {test: [{str: 'yay!'}]}); // undefined