Skip to content

Spreading possibly undefined variable results in empty object type union #18000

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

Closed
ajafff opened this issue Aug 24, 2017 · 5 comments
Closed
Assignees
Labels
Bug A bug in TypeScript Duplicate An existing issue was already created

Comments

@ajafff
Copy link
Contributor

ajafff commented Aug 24, 2017

TypeScript Version: 2.5.1
Code

function foo(a: {[key: string]: string}, b?: {[key: string]: string}) {
    a = {...b, ...a};
}

Expected behavior:
No Error

Actual behavior:

Type '{} | { [x: string]: string; }' is not assignable to type '{ [key: string]: string; }'.
  Type '{}' is not assignable to type '{ [key: string]: string; }'.
    Index signature is missing in type '{}'.
@kitsonk
Copy link
Contributor

kitsonk commented Aug 24, 2017

Just to note it works without error in playground. Feels like some sort of regression.

@ajafff
Copy link
Contributor Author

ajafff commented Aug 24, 2017

I tested 2.4.2, 2.5.0 and 2.5.1. All of them produce this error.
So this must be a regression somewhere between 2.4.0 and 2.4.2

@mhegazy mhegazy added the Bug A bug in TypeScript label Aug 24, 2017
@jambonrose
Copy link

I'm new to TypeScript, but enjoying it immensely - Thank you!

I believe I've just run into the same problem with typescript 2.5.2 .

export interface IFormAction {
  type: FormActions // an enum not shown here
}
export interface IFormState {
  [formName: string]: {
    [fieldName: string]: string
  }
}
export interface IFormReducer {
  (state?: IFormState, action?: IFormAction): IFormState
}
export const reducer: IFormReducer = (
  state, action = { type: FormActions.none }
) => {
  const defaultState: IFormState = {}
  return {
    ...defaultState,
    ...state,
  }
}
src/forms/reducer.ts(42,14): error TS2322: Type '(state: IFormState | undefined, action?: IFormAction | undefined) => {} | { [x: string]: { [field...' is not assignable to type 'IFormReducer'.
  Type '{} | { [x: string]: { [fieldName: string]: string; }; }' is not assignable to type 'IFormState'.
    Type '{}' is not assignable to type 'IFormState'.
      Index signature is missing in type '{}'.

As noted by @ajafff , this seems to be related to object spreads, as removing them removes the error.

export const reducer: IFormReducer = (
  state, action = { type: FormActions.none }
) => {
  const defaultState: IFormState = {}
  return defaultState // compiles no problem
}

Note that explicitly adding | {} onto the relevant type appears to provide a workaround.

export interface IFormReducer {
  (state?: IFormState, action?: IFormAction): IFormState | {}
}
// reducer uses spread as before, but compiles without issue

Hope this is helpful.

@jambonrose
Copy link

I believe that #16694 and #17849 reference the same issue.

@mhegazy mhegazy added this to the TypeScript 2.6 milestone Sep 12, 2017
@mhegazy
Copy link
Contributor

mhegazy commented Oct 9, 2017

Duplicate of #16694

@mhegazy mhegazy marked this as a duplicate of #16694 Oct 9, 2017
@mhegazy mhegazy closed this as completed Oct 9, 2017
@mhegazy mhegazy added the Duplicate An existing issue was already created label Oct 9, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants