0

I want to write a function that converts a specific value in an object from string to a number.

Here is my function:

export function convertStringToNumber<K extends string>(
  obj: Record<K, object>,
  val: string
): Record<K, number> {
  const result: Partial<Record<K, unknown>> = {}
  for (const key in obj) {
    if (key === val) {
      result[key] = Number(obj[key])
    } else {
      result[key] = obj[key]
    }
  }
  return result as Record<K, number>
}

My function is working, but my TypeScript is complaining about the types. Can TypeScript take the input types and just change the type of an appropriate key to a number?

I have a second version, perhaps this one is more appropriate:

export function convertStringToNumber2<T> (
  obj: T,
  val: string
): T {
  const result: Partial<T> = {}
  for (const key in obj) {
    if (key === val) {
      result[key] = Number(obj[key])
    } else {
      result[key] = obj[key]
    }
  }
  return result
}

TypeScript is complaining: Type 'number' is not assignable to type 'T[Extract<keyof T, string>]'.ts(2322)

0

1 Answer 1

1

By using two generics, you can derive a return type from your inputs with the help of the utility types Omit<Type, Keys> and Record<Keys, Type>, like this:

TS Playground

function convertStringToNumber <
  O extends Record<string, unknown>,
  K extends keyof O
>(obj: O, key: K): Omit<O, K> & Record<K, number> {
  return {...obj, [key]: Number(obj[key])};
}

const input = {
  a: "1",
  b: "2",
  c: "x",
};

const output1 = convertStringToNumber(input, "a");
console.log(output1); // { a: 1, b: "2", c: "x" }

const output2 = convertStringToNumber(input, "c");
console.log(output2); // { a: "1", b: "2", c: NaN }

Compiled JS from the TS Playground:

"use strict";
function convertStringToNumber(obj, key) {
    return { ...obj, [key]: Number(obj[key]) };
}
const input = {
    a: "1",
    b: "2",
    c: "x",
};
const output1 = convertStringToNumber(input, "a");
console.log(output1); // { a: 1, b: "2", c: "x" }
const output2 = convertStringToNumber(input, "c");
console.log(output2); // { a: "1", b: "2", c: NaN 

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.