Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

typescript object type with generic result syntax error

i get syntax error when when trying to assign value as the result of generic Merge into object type(type of key-value)

type Merge<a,b> = any

type test<P, S= any, K= any> = {
    jsx1?: (state: Merge<K, S>, props: P, nextJsx?) => JSX.Element; //ok
    jsx2?: ({state: S, props: P, nextJsx}) => JSX.Element; // ok
    jsx3?: ({ state: Merge<K, S>, props: P, nextJsx }) => JSX.Element; // error - why?
    //                    ^ webstorm: ", expected"     ^ vscode: ';' expected.(1005)
};

IDE: webstorm

why is that considered syntax error? how can I assign jsx3->state to type Merge

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

typescript 4.4.4.

in vs code: very similar result but the error is ';'expected.ts(1005) on the arrow function. same error in ts playground:

Playground

>Solution :

In the signature ({state: S, props: P, nextJsx}) => JSX.Element, S and P are not types, they are identifiers. In this context, the colon : does not mean a type annotation, it means rebinding the name of a property, like in the following example:

const obj = {foo: 23};

// bar is not a type annotation here
const {foo: bar} = obj;

// 23
console.log(bar);

I’m not sure what the usefulness of parameter rebinding would be in a type declaration, but for better or worse, that’s what it means. So the error is because Merge<K, S> is not a valid identifier for rebinding; but in fact both your jsx2 and your jsx3 declarations have problems, it’s just that you didn’t get an error for the other one.

The solution is to put the types in a place where, contextually, they actually are types; i.e. in the parameter’s type annotation.

type Test<P, S=any, K=any> = {
    jsx1?: (state: Merge<K, S>, props: P, nextJsx?) => JSX.Element;
    jsx2?: (params: {state: S, props: P, nextJsx}) => JSX.Element;
    jsx3?: (params: {state: Merge<K, S>, props: P, nextJsx}) => JSX.Element;
}

Note the parameter is a single object named params, and its type now occurs in a type annotation context so it is not parsed as rebinding identifiers. Also, although there is a single named parameter params in the type declaration, it is still perfectly possible to do parameter destructuring (and rebinding, if you want to) when you actually implement these functions:

const test: Test<number, number, number> = {
    jsx2: ({state, props, nextJsx}) => console.log(state, props, nextJsx),
    jsx3: ({state, props, nextJsx}) => console.log(state, props, nextJsx),
};

Playground Link

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading