1

I am new to typescript and was wondering if there was a way to map a string value to a custom type when calling functions with templates?

for example:

object.method<TypeMapper['CustomType']>([...])

where in this case CustomType may be a custom interface such as:

interface CustomType {
x: number,
y: number
}

and the the javascript code would resolve to object.method<CustomType>([...])

My code:

interface CustomType {
  x: number,
  y: number
}

interface TypeMapper { 'CustomType': CustomType }

type Test = TypeMapper['CustomType'] // CustomType

function func<T>(x: number, y: number) {
  let v: T;
}
const typeVariable = 'CustomType';
const z = func<TypeMapper[typeVariable]>(1,2);
// 'typeVariable' refers to a value, but is being used as a type here.
// Did you mean 'typeof typeVariable'?(2749)
5
  • interface TypeMapper { 'CustomType': CustomType} like this? Commented Nov 9, 2021 at 22:32
  • yes something along those lines, however when i try to use that exact syntax I get an error that generally says: Error: type expected but found value Commented Nov 9, 2021 at 22:37
  • could you show the code you tried that didn't work then? An interface shouldn't say "found value" Commented Nov 9, 2021 at 22:38
  • 1
    @TadhgMcDonald-Jensen's solution works fine typescriptlang.org/play?#code/… Please post a minimal reproducible example. Commented Nov 9, 2021 at 23:23
  • @AlexWayne I have modified the sandbox: link It should now show the error that i am encountering Commented Nov 10, 2021 at 15:39

1 Answer 1

1

That error tells you how to fix it:

'typeVariable' refers to a value, but is being used as a type here. Did you mean 'typeof typeVariable'?(2749)

The type system can't act on values directly. You need to convert a value to the type of that value with the typeof keyword.

const typeVariable = 'CustomType';
type Z = TypeMapper[typeof typeVariable] // identical to: type Z = CustomType

And now if you hover over func on this line

const z = func<TypeMapper[typeof typeVariable]>(1,2);

It should tell you it is this type:

function func<CustomType>(x: number, y: number): void

Which seems to be what you are looking for.

Playground


I am using a string variable that is not defined at compile time

Well that's a bit of a problem. Types only exist at compile time, so if you don't know it at compile time, then you have to manually test at runtime.

With this function:

function func1(type_string: string) {
  type t = TypeMapper[typeof type_string];
}

It's perfectly valid to pass in any string, since that's how the function is typed. So if you pass "BadString", then what do you expect t to be?

To make this example work, you have to narrow the type string to more specific types to know if the value is safe to use.

For example:

function func1(type_string: string) {
  if (type_string === 'CustomType') {
    type t = TypeMapper[typeof type_string]; // works
  } else {
    throw new Error(`Unknown type string: ${type_string}`)
  }
}

Playground

There are a lot of ways to do narrowing, but it's hard to advise more on which to use from this very contrived code.

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

2 Comments

Thanks for your answer, for the specific use case that I am using, I am using a string variable that is not defined at compile time, I have updated the playground Can you review this
I've updated my answer with more on that case.

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.