I have a function that receives a value and default value, if the value is a boolean then I want the return type to be the type of the incoming default type.
Heres the function:
export type InferStyledValue<T> = (
value: string | number | boolean | undefined,
def: T
) => T;
export const inferStyledValue: InferStyledValue<T> = (value, def) => {
if (typeof value === "string") return value;
if (typeof value === "number") return `${value}px`;
if (typeof value === "boolean") return value && def;
return def;
};
The default values look like this:
The default values don't currently contain number types but I plan on adding them
const defaults = {
width: "100%",
height: "100%",
padding: "0",
margin: "0",
border: { width: "2px", radius: "8px", color: "#DDDDDD" },
};
The function call looks like this:
inferStyledValue(border.radius, defaults.border.radius)
Any help will be greatly appreciated thank you.
CodePudding user response:
to be honest this approach is not good and will often lead to bugs in your code if not used properly but here's an approach that will work for you:
function inferStyledValue(def: string, val?: string | number): string;
function inferStyledValue(
def: boolean,
val?: boolean | 'true' | 'false' | 0 | 1
): boolean;
function inferStyledValue(def: number, val?: string | number): number;
function inferStyledValue(def: any, val?: any) {
if (typeof def === 'string' && typeof val === 'string') return val;
if (typeof def === 'string' && typeof val === 'number') return `${val}px`;
if (typeof def === 'number' && typeof val === 'number') return val;
if (typeof def === 'number' && typeof val === 'string')
return parseInt(val, 10) || def;
if (typeof def === 'boolean' && typeof val === 'boolean') return val;
if (
typeof def === 'boolean' &&
(typeof val === 'string' || typeof val === 'number')
)
return Boolean(val);
return def;
}
const defaults = {
width: '100%',
height: '100%',
padding: '0',
margin: '0',
border: { width: true, radius: 1, color: '#DDDDDD' },
};
const inferreBool = inferStyledValue(defaults.border.width); // boolean , only accepts boolean | 'true' | 'false' | 0 | 1
const inferredNum = inferStyledValue(defaults.border.radius, '10'); // number , only accepts string | number
const inferredStr = inferStyledValue(defaults.border.color, 10); // string , only accepts string | number -> output '10px' (?)
You can change the overload signature and inside logic based on your needs.