Home > Software engineering >  Access parameter types in function type
Access parameter types in function type

Time:04-30

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.

  • Related