question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Suggestion: Noninferential type parameter usage

See original GitHub issue

We keep getting bugs like this and I keep not finding the original so I’m making a new one so we can find it.

Keywords: ignore type parameter optional inference

Problem

Often with generics, there will be some locations where a type parameter should be inferrable from usage, and other places where the type parameter should only be used to enforce typechecking. This comes up in a variety of contexts

class Animal { move }
class Dog extends Animal { woof }

function doSomething<T>(value: T, getDefault: () => T) { }
// Wanted an error here - getDefault() ought to return same type as 'value'
doSomething(new Dog(), () => new Animal());
declare function assertEqual<T>(actual: T, expected: T): boolean;
const g = { x: 3, y: 2 };
assertEqual(g, { x: 3 }); // Forgot y, wanted error

Proposal Sketch

We should be able to mark type parameter consumption sites as being “not eligible for inference”. For example, let’s say we had a special global type that the compiler knew not to unwrap during inference:

type NoInfer<T> = T;

Then we can annotate usage sites

function doSomething<T>(value: T, getDefault: () => NoInfer<T>) { }
// Wanted an error here - getDefault() ought to return same type as 'value'
doSomething(new Dog(), () => new Animal());
declare function assertEqual<T>(actual: T, expected: NoInfer<T>): boolean;
const g = { x: 3, y: 2 };
assertEqual(g, { x: 3 }); // Error

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:112
  • Comments:27 (13 by maintainers)

github_iconTop GitHub Comments

43reactions
jcalzcommented, Jun 20, 2019

How about we use the compiler’s deferral of evaluating unresolved conditional types?

type NoInfer<T> = [T][T extends any ? 0 : never];
19reactions
ajafffcommented, Aug 14, 2017

T & {} only works when not using strictNullChecks. I encountered a problem when T is undefined, because undefined is not assignable to undefined & {}.

I found that mapped types also defer inference, so i tried type InferLast<T> = Readonly<T>; That does not work for types with index signatures like arrays.

My final solution is a mapped type intersected with the type itself:

export type NoInfer<T> = T & {[K in keyof T]: T[K]};
Read more comments on GitHub >

github_iconTop Results From Across the Web

Tomer Aberbach on Twitter: "So apparently TypeScript infers ...
Trying to rework an API and TypeScript type inference has me very ... Suggestion: Noninferential type parameter usage · Issue #14829 ...
Read more >
TypeScript: Override Generic Types in Method<T> that inherit ...
It seems like you just want to let callers use these type parameters as if they were using type assertions, like create("hey") as...
Read more >
Constraints on type parameters - C# Programming Guide
Constraints specify the capabilities and expectations of a type parameter. Declaring those constraints means you can use the operations and ...
Read more >
Generic Types - Learning the Java Language
It specifies the type parameters (also called type variables) T1, T2, ..., and Tn. To update the Box class to use generics, you...
Read more >
Type Parameters Proposal
Parameterized types and functions may use operators with type parameters, ... We suggest that types be extended to take type parameters.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found