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.

Contravariance broke in 3.8 when combining spreading parameter list with conditional type

See original GitHub issue

TypeScript Version: 3.8.3

Search Terms: variance contravariance

Description: An Injector in typed-inject is a dependency injection container that is type safe. It can only provide values for tokens it knows. A small example:

declare const fooInjector: Injector<{foo: string}>; // this injector can provide string values for the token 'foo'
const foo = fooInjector.resolve('foo'); 
// => typeof foo === 'string'
fooInjector.resolve('bar');
// => Error ts(2345) Argument of type '"bar"' is not assignable to parameter of type '"foo"'

It makes sense that an injector Injector<{}> is not assignable to Injector<{foo: string}>, since it cannot provide a value for token 'foo'. This was the case in TS 3.7. However, since TS 3.8, Injector<{}> is assignable to Injector<{foo: string}> 😪.

declare const rootInjector: Injector<{}>;
const fooInjector: Injector<{ foo: string}> = rootInjector;

Expected behavior: Type 'Injector<{}>' is not assignable to type 'Injector<{ foo: string; }>'.

Actual behavior: No error

Related Issues: Couldn’t find any 🤷‍♂️

Code

I think I’ve trimmed it down to the essentials.

interface Injector<TContext> {
  injectFunction<Tokens extends (keyof TContext)[]>(todo:
    (...args: { [K in keyof Tokens]: Tokens[K] extends keyof TContext ? TContext[Tokens[K]] : never; }) => void): void;
} 

declare const rootInjector: Injector<{}>;
const fooInjector: Injector<{ foo: string}> = rootInjector;
Output

(none)

Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": 2,
    "target": "ES2017",
    "jsx": "React",
    "module": "ESNext"
  }
}

Playground Link: Provided

Simpler contravariant examples like this still work as expected.

type Action<T> = (arg: T) => void;
declare let b: Action<{}>;
declare let a: Action<{foo: number}>;
b = a
// => Error! Type 'Action<{ foo: number; }>' is not assignable to type 'Action<{}>'.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:4
  • Comments:11 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
sandersncommented, Mar 16, 2021

I closed #31029 because it had been sitting stale for a year after we decided in the design meeting that it needed some more design work. It’s still worthwhile to follow up on the design meeting recommendations and see if they work out.

1reaction
weswighamcommented, Oct 30, 2020

Based on my understanding on the workings of the problem, yes.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Issues · microsoft/TypeScript · GitHub
Contravariance broke in 3.8 when combining spreading parameter list with conditional type Blocked A fix for this issue is blocked on another fix...
Read more >
Covariance and Contravariance in Generics - Microsoft Learn
Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types.
Read more >
The starting point for learning TypeScript
Learn how to write declaration files to describe existing JavaScript. Important for DefinitelyTyped contributions. Introduction · Declaration Reference ...
Read more >
https://raw.githubusercontent.com/microsoft/TypeSc...
TypeParameter // type parameters are visible in parameter list, ... type parameter declared using 'infer T' in a conditional type is visible only...
Read more >
The Structural Mechanics Module User's Guide
For a list of all the core physics interfaces included with a COMSOL ... This is a multiphysics combination of solid mechanics, electric...
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