-
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
JS classes extending generic TS classes should not use specified default type parameters #17104
Comments
Another workaround is to use spread operator (see #16725). The bad thing that it is considered a bug. |
Can confirm with latest version of TS - works fine only if JS component has no props. Really sad issue and breaks whole migration process from JS to TS :( I beleive it can be solved via https://www.typescriptlang.org/docs/handbook/jsx.html and specifying typings for comonents but would be much easier if all JS components could be imported as |
Just tried with latest '2.5.0-dev.20170712' and with master - same issue |
Running into the exact same issue. Absolute blocker for converting our app to typescript. Can get around it with something like this:
But obviously hacky and prevents good linting practice. Any movement on this? |
So I believe I understand the core of the problem. The default generics for React Component specify propShape as {}, which is what typescript assumes to be used as the default props for any jsx component. Thus, typescript validates the components, thinking that they shouldn't have any props. You can get around this by creating your own base react class: // baseClass.ts
import React, {Component} from 'react';
export default class ReactComponent<P = any, S = any> extends Component<P, S> {
} Your jsx components will need to extend this class instead. Not ideal. Another solution I haven't investigated is to see if there is a way to override the generics of @types/react/index.d.ts: interface Component<P = {}, S = {}> extends ComponentLifecycle<P, S> { } to this: interface Component<P = any, S = any> extends ComponentLifecycle<P, S> { } unfortunately, you can't just override these definitions with declaration merging. |
Yeah, seems like the underlying reason is that Typescript respects default generic types when processing JS classes extending TS generic classes. So, here is more minimalistic example without React and JSX generic.ts export default class Generic<T> {
f(x: T) {
return x;
}
} genericDef.ts export default class GenericDef<T = {}>{
f(x: T) {
return x;
}
} hello.js import Generic from "./generic";
export class Hello extends Generic {} helloDef.js import GenericDef from "./genericDef";
export class HelloDef extends GenericDef {} index.ts import {Hello} from './hello';
import {HelloDef} from './helloDef';
import Generic from "./generic";
import GenericDef from "./genericDef";
let x: Generic<{x: number}> = new Hello();
// ^^ OK
let y: GenericDef<{x: number}> = new HelloDef();
// ^^
// index.ts(7,5): error TS2322: Type 'HelloDef' is not assignable to type 'GenericDef<{ x: number; }>'.
// Types of property 'f' are incompatible.
// Type '(x: {}) => {}' is not assignable to type '(x: { x: number; }) => { x: number; }'.
// Type '{}' is not assignable to type '{ x: number; }'.
// Property 'x' is missing in type '{}'. tsconfig.json {
"compilerOptions": {
"module": "es2015",
"target": "esnext",
"strictNullChecks": true,
"allowSyntheticDefaultImports": true,
"allowJs": true,
"lib": [
"es5",
"es6",
"es7",
"es2017",
"dom"
],
"outDir": "dist"
},
"include": [
"**/*.ts",
"**/*.js"
],
"exclude": [
"node_modules"
]
} A repo with this example: https://github.com/gagarski/ts-js |
Does annotating your JavaScript class to specify the generic arguments help (e.g. #15251 (comment) )? |
In a .js file does there is no mean to specify generic type arguments, that is why the compiler tries to figure them out as much as it can, and does not report errors for them. use |
@billti @mhegazy However, default generic parameters do not seem a good source of truth for generic parameters of JS classes. Generic parameters in JS are omitted exactly because there is not mean to specify them, not because JS developer intended to rely on TS default generic parameters (he probably thought something like "Typescript? What is Typescript?" when he was writing this code). In this case the most we can rely on is If it is intended behaviour and the guess about default generic parameters is right in most cases, then we probably should close this issue. |
The default comes from the author of the declaration file. the default can be |
I still think that it's better to consider generic parameters information lost when the typed class goes through a typeless JS gap than to make inaccurate guess based on default argument, but maybe I totally misunderstand the whole purpose of default generic parameters :) Also React typings seem correct for me (if you don't specify state type, you probably don't want state at all). |
@psachs21 probably the |
Yeah, the @Augments makes the most sense to me. I was unaware that was an
option but it works great.
…On Mon, Aug 21, 2017 at 7:22 PM Kirill Gagarski ***@***.***> wrote:
@psachs21 <https://github.com/psachs21> probably the @Augments solution
is much cleaner than hacking base classes in all of your JS files.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#17104 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AK61gEijL2V6PITOC2Eve760P9d294Edks5sahE1gaJpZM4OUyt6>
.
|
This code is also working: const helloProps = { baz: "world" }
<Hello {...helloProps} /> However at least it doesn't need to edit jsx files |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
I think I'm having a similar issue... /**
* @type {Reducer<IPoiState, any>}
*/
const poi = handleActions({
[ADD_BOOKMARK_START]: (state) => {
return { ...state };
},
}, {}); The export function handleActions<State>(
reducerMap: ReducerMap<State>,
initialState: State
): Reducer<State, any>; So, I'm getting an error saying that...
Is there anyway to force the generic through? |
See minified description and example at the comment below
Here is original description involving React and JSX
The text was updated successfully, but these errors were encountered: