-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Unexpected error when using generic with Pick and Exclude #28748
Comments
I am also having this issue with version EDIT: I was able to work around this issue like so: |
Same problems here too. |
Same problem for me. export type Injector<P> = <T extends P>(Component: React.ComponentType<T>) => React.ComponentType<Subtract<T, P>>;
export type Subtract<T, K> = Omit<T, keyof K>;
export type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
const withContext: Injector<Context> = (Component) => (props) => (
<ContextProvider>{(context) => <Component {...context} {...props} />}</ContextProvider>
); |
@sledorze just curious, did you find any satisfactory workarounds for this? Unfortunately it's preventing us from upgrading to TS 3.2 at the moment |
@jkillian not using Pick, not relying on key selection. going from something like export const myHoc = function<ComposedComponentProps extends UserProp>(
ComposedComponent: ComponentType<ComposedComponentProps>,
) ... ```
to
```ts
export const myHoc = function<ComposedComponentProps>(
ComposedComponent: ComponentType<ComposedComponentProps & UserProp>,
) Unfortunately, the downside is that the types you are using must be some explicit intersection in order to infer the types correctly. That means no more using interfaces. I hope Typescript will provide some means to tackle this (maybe that's the case with the last version, but I'm slashing code on the backend ATM - so will not be using Typescript until 2019..). |
It will be great to hear from @typescript team if this is really a bug in 3.2.2 version or it means that previously our react HOC were typed incorrectly. I have tried adopting a @iiroj proposed workaround, and it actually fixes TS error in HOC, but cause another issue. TS requires an injected prop on the wrapped component. Example
when I replace
I don't really want to make |
@vict-shevchenko see my example here: https://github.com/iiroj/breakpoint-observer/blob/master/stories/withBreakpoint.story.tsx Here the |
Hi, @iiroj, I have analyzed your example and made a small reproducible scenario based on it. Truthfully results are somehow confusing. I made a conclusion that your example work correctly only because you pass Here is a code snippet: import * as React from "react";
interface NameInterface {
name: string;
};
function withName<P extends object>(Component: React.ComponentType<P & NameInterface>) {
return function (props: P) {
return (
<Component
{...props}
name={'John'}
/>
);
}
}
const UnNamed_1: React.SFC<NameInterface> = ({ name }) => (<p>My name is {name}</p>);
const Named_1 = withName(UnNamed_1);
<Named_1 /> // Property 'name' is missing in type '{}' but required in type 'NameInterface'.ts(2741)
interface UnNamedPropsInterface extends NameInterface {
age: number;
}
const UnNamed_2: React.SFC<UnNamedPropsInterface> = ({ name, age }) => (<p>My name is {name} and {age}</p>);
const Named_2 = withName(UnNamed_2);
<Named_2 age={30} /> // Property 'name' is missing in type '{ age: number; }' but required in type 'UnNamedPropsInterface'.ts(2741)
type UnNamedType = NameInterface;
const UnNamed_3: React.SFC<UnNamedType> = ({ name }) => (<p>My name is {name}</p>);
const Named_3 = withName(UnNamed_3);
<Named_3 /> // Property 'name' is missing in type '{}' but required in type 'NameInterface'.ts(2741)
type UnNamedType_2 = NameInterface & { age: number };
const UnNamed_4: React.SFC<UnNamedType_2> = ({ name, age }) => (<p>My name is {name} and {age}</p>);
const Named_4 = withName(UnNamed_4);
<Named_4 age={30} /> // All OK, but why? Can someone please advise. |
Ah, so I see mine’s not really workaround but just just happens to work because of the optional props (window, and thus width doesn’t exist during SSR). |
Updated my original post with a much simpler example: const fn = <Params>(
params: Pick<Params, Exclude<keyof Params, never>>,
): Params => params; |
Also spent nearly one whole day and found this issue... How dumb I am 😭 |
@aprilandjan You're not alone :-) I was following some examples and I just didn't get it to work. I thought I was doing something wrong, but it broke with TypeScript v3.2. I have found a workaround to "fix" this issue. It's a fairly simple fix and you can apply it by spreading the properties as
into
and the error is gone. |
Hi Guys. Heres my complete (simplified) example which worked with TS 3.1 but does not work with TS 3.2 import * as React from "react"
const AuthContext = React.createContext({})
export type Omit<T, K extends string> = Pick<T, Exclude<keyof T, K>>
export interface IAuthContext {
currentUser: string
}
export interface IAuthContextProp {
auth: IAuthContext
}
export function withAuthContext<
TComponentProps extends IAuthContextProp,
TWrapperProps = Omit<TComponentProps, keyof IAuthContextProp>
>(
Component: React.ComponentType<TComponentProps>
): React.ComponentType<TWrapperProps> {
return (props: TWrapperProps): React.ReactElement<TComponentProps> => (
<AuthContext.Consumer>{(auth) => (
<Component auth={auth} {...props} />
)}</AuthContext.Consumer>
)
} The error in TS 3.2 (on the
Thanks for your workaround @ramondeklein , it works nicely. I wonder if this could be a problem with the React typings? For reference I am on |
Is this the same problem? What we are doing has really nothing to do with my example here, but it is the simpler way to reproduce the same problem that I found. interface ValueWrapper<V> {
value: V;
}
interface StringValue extends ValueWrapper<string> {
fontSize: number;
}
const foo: Exclude<StringValue, ValueWrapper<string>> = {
// Type 'number' is not assignable to type 'never'. [2322]
fontSize: 2
}; Used to work with TypeScript 3.1.1 and is preventing us from upgrading. |
Hmm, so it looks like fixing this was on the roadmap for TS 3.3, but then it got removed, and it was briefly on the milestone for 3.4 but got removed from that too, so I'm not sure when this will be addressed. 😞 That said, I ended up using the workaround proposed in #28748 (comment). While seeing |
The original examples are fixed in 3.4.1 (by #29437?), however some issues seem to remain: const fn = <Params, Key extends keyof Params>(
params: Pick<Params, Key> & Pick<Params, Exclude<keyof Params, Key>>
): Params =>
// Unexpected error
// Type 'Pick<Params, Key> & Pick<Params, Exclude<keyof Params, Key>>' is not assignable to type 'Params'.
params; I guess this is a separate issue? /cc @weswigham @RyanCavanaugh |
@OliverJAsh Isn't that related to #28884? |
Aye. |
same problem +1 TypeScript version: |
Still same issue with running yarn but npm works fine |
TypeScript Version: 3.2.1
Search Terms: generic pick exclude
Code
The text was updated successfully, but these errors were encountered: