A
A
Alexandroppolus2021-08-26 20:20:09
typescript
Alexandroppolus, 2021-08-26 20:20:09

How to correctly tell the typescript about type inference in a template function?

Essence:

type Value<T> = (() => T) | T

function funcStr(value: Value<string>): string {
  return typeof value === 'function' ? value() : value
}

function funcTpl<T>(value: Value<T>): T {
  return typeof value === 'function' ? value() : value
}


The function receives a certain value as input, if it turned out to be a function, it returns the result of the call, otherwise the value itself.
In funcStr everything is fine, but in funcTpl there is an ambush: checking typeof value === 'function' turns the value type not into (() => T) , as intended, but into (() => T) | (T & Function)
Apparently, the fact is that T can be a function, and TS is trying to somehow expand / use this business ..

How to do it right? Yes, you can rape (value as (() => T))(), but that's not the ts-way.

Update:
T can be a function, i.e. maybe
funcTpl(() => ()=>{})

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Belyaev, 2021-08-26
@Alexandroppolus

Option 1, use a custom type guard:

type Value<T> = (() => T) | T

function isFunctionValue<T>(value: Value<T>): value is () => T {
    return typeof value === 'function'
}

function funcStr(value: Value<string>): string {
  return isFunctionValue(value) ? value() : value
}

function funcTpl<T>(value: Value<T>): T {
  return isFunctionValue(value) ? value() : value
}

Option 2, exclude the possibility of a function from T:
type Value<T> = T extends (...args: never[]) => unknown ? never : (() => T) | T

function funcStr(value: Value<string>): string {
  return typeof value === 'function' ? value() : value
}

function funcTpl<T>(value: Value<T>): T {
  return typeof value === 'function' ? value() : value
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question