microsoft / microsoft/TypeScript
Assigning a callable return type of a generic function directly to some generic parameter results in error
Nessuno ha ancora preso questa issue.
- Lingua principale
- Go
- Stelle
- 111k
- Fork
- 14.3k
- Merge medio
- 2g 4h
- PR unite (30g)
- 132
Descrizione
TypeScript Version: above 3.3.3
Code
To see the actual behavior depending on a version of TS it is better to open the code below in the playground
type Callable<T> = { (t: T): any; };
declare function utilA<T>(
callable: Callable<T>,
fn: (t: T) => any
): any
declare function utilB<T>(
callable: Callable<T>,
params: {
fn: (t: T) => any
}
): any
declare function utilC<T>(
params: {
callable: Callable<T>,
fn: (t: T) => any
}
): any
/**
* Case 1: directly assigning a callable
*/
declare const callable: Callable<number>
utilA(
callable,
t => t.toExponential() // t is a number, OK
)
utilB(
callable,
{
fn: t => t.toExponential() // t is a number, OK
}
)
utilC({
callable,
fn: t => t.toExponential() // t is a number, OK
})
/**
* Case 2: directly assigning the result of a function returning a callable
*/
declare function computeCallableA(): Callable<number>
utilA(
computeCallableA(),
t => t.toExponential() // t is a number, OK
)
utilB(
computeCallableA(),
{
fn: t => t.toExponential() // t is a number, OK
}
)
utilC({
callable: computeCallableA(),
fn: t => t.toExponential() // t is a number, OK
})
/**
* Case 3: directly assigning the result of a generic function returning a callable
*/
declare function computeCallableB<T>(t: T): Callable<T>
utilA(
computeCallableB(100),
t => t.toExponential() // t is a number, OK
)
utilB(
computeCallableB(100),
{
fn: t => t.toExponential() // t is a number, OK
}
)
utilC({
callable: computeCallableB(100), // Error
fn: t => t.toExponential() // t is an unknown
})
/**
* The last case is strange IMO. The result type of `computeCallableB` is immediately known.
*
* Hovering the last `utilC` shows the following:
*
* function utilC<number>(params: {
* callable: Callable<number>;
* fn: (t: number) => any;
* }): any
*
* Despite the fact that TS infers generic `T` of `utilC`, assignment to `callable` param
* gives: "Type 'Callable<number>' is not assignable to type 'Callable<unknown>'.".
*
* It is hard to understand whats going on. More than that, everything works in TS v3.3.3.
* In newer versions the behavior is broken.
*
* This has an impact on the library I help to maintain. Such use cases are not rare and
* people are forced to assign the result of `computeCallableB(100)` to a variable first,
* and then to a `callable` parameter, which affects DX:
*/
const computeCallableBResult = computeCallableB(100)
utilC({
callable: computeCallableBResult, // This works!
fn: t => t.toExponential() // t is a number, OK
})
Expected behavior:
The invocation of
utilC({
callable: computeCallableB(100), // Error
fn: t => t.toExponential() // t is an unknown
})
gives no errors.
Actual behavior:
Strange behavior in versions above 3.3.3.
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia aprendo la riproduzione collegata di TypeScript Playground e confronta le chiamate di Case 3 con i casi funzionanti e con il comportamento in TypeScript 3.3.3. Analizza l’inferenza generica per l’oggetto inline utilC quando callable riceve computeCallableB(100). Il lavoro è completato quando la chiamata inline non produce errori e inferisce t come number, senza richiedere una variabile intermedia.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- typescript
- Ambito
- compilers
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 42/100