Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression for inferred unions in generic parameters #33490

Closed
eps1lon opened this issue Sep 18, 2019 · 5 comments · Fixed by #34607
Closed

Regression for inferred unions in generic parameters #33490

eps1lon opened this issue Sep 18, 2019 · 5 comments · Fixed by #34607
Assignees
Labels
Bug A bug in TypeScript Domain: Type Inference Related to type inference performed during signature resolution or `infer` type resolution Fix Available A PR has been opened for this issue

Comments

@eps1lon
Copy link
Contributor

eps1lon commented Sep 18, 2019

TypeScript Version: 3.7.0-dev.20190918

Search Terms: infer generic

Code

// simpler react types
declare class Component<P> {
  props: P;
}

export type ComponentClass<P> = {
  new (props: P): Component<P>;
};

export type FunctionComponent<P> = (props: P) => null;

export type ComponentType<P> = FunctionComponent<P> | ComponentClass<P>;

// simpler react-router.d.ts
export interface RouteComponentProps {
  route: string;
}

declare function withRouter<
  P extends RouteComponentProps,
  C extends ComponentType<P>
>(
  component: C & ComponentType<P>
): ComponentClass<Omit<P, keyof RouteComponentProps>>;

interface Props extends RouteComponentProps {
  username: string;
}

declare const MyComponent: ComponentType<Props>;

// If I define `ComponentType` as `ComponentClass<P> | FunctionComponent<P>`:
// Argument of type 'ComponentType<Props>' is not assignable to parameter of type 'ComponentClass<Props> | (ComponentClass<Props> & FunctionComponent<Props>)'.
// If I define `ComponentType` as `FunctionComponent<P> | ComponentClass<P>`:
// Argument of type 'ComponentType<Props>' is not assignable to parameter of type 'FunctionComponent<Props> | (FunctionComponent<Props> & ComponentClass<Props>)'.
withRouter(MyComponent);

C & ComponentType<P> helps inference. For a more comprehensive test suite check the react-router declarations and tests

A fix getting rid of C & ComponentType<P> (DefinitelyTyped/DefinitelyTyped#38326) caused issues when using strictFunctionTypes

Expected behavior:
No type error

Actual behavior:
Throws with a different error message depending on the order of the union members in ComponentType

Playground Link:
playground for 3.5.3

Related Issues:

/cc @OliverJAsh

@eps1lon
Copy link
Contributor Author

eps1lon commented Sep 18, 2019

Oh and

-component: C & ComponentType<P>
+component: C & (C extends ComponentClass<P> ? ComponentClass<P> : FunctionComponent<P>)

fixes any error and passes the full test suite down until 3.0. 3.1 and above will pass while 3.0 will fail.

@waynebloss
Copy link

I'm just trying to use jsdoc in vscode (v1.38.1) to document types and the following doesn't work. Is this the same bug?

My issue is that Intellisense shows function xxx(yyy: any): any for:

/** @param {string | number | (zzz:string)=>string} yyy */
function xxx(yyy) {
  return yyy;
}

Intellisense shows function xxx(yyy: (zzz: string) => string): (zzz: string) => string for:

/** @param {(zzz:string)=>string} yyy */
function xxx(yyy) {
  return yyy;
}

Intellisense shows function xxx(yyy: string | number): string | number for:

/** @param {string | number} yyy */
function xxx(yyy) {
  return yyy;
}

@j-oliveras
Copy link
Contributor

@waynebloss your first code should be wrote as (see the parenthesis around lambda):

/** @param {string | number | ((zzz:string)=>string)} yyy */
function xxx(yyy) {
    return yyy;
}

@weswigham weswigham added Bug A bug in TypeScript Domain: Type Inference Related to type inference performed during signature resolution or `infer` type resolution labels Sep 18, 2019
@weswigham
Copy link
Member

I suspect this regressed because of #32558.

@ahejlsberg
Copy link
Member

ahejlsberg commented Oct 21, 2019

Simpler repro:

type AB<T> = { a: T } | { b: T };

// T & AB<U> normalizes to T & { a: U } | T & { b: U } below
declare function foo<T, U>(obj: T & AB<U>): [T, U];
declare let ab: AB<string>;

let z = foo(ab);  // Expect [AB<string>, string]

Regression was indeed caused by #32558.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: Type Inference Related to type inference performed during signature resolution or `infer` type resolution Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants