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

Strange behavior in function type inference #1926

Closed
fdecampredon opened this issue Feb 4, 2015 · 7 comments
Closed

Strange behavior in function type inference #1926

fdecampredon opened this issue Feb 4, 2015 · 7 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@fdecampredon
Copy link

I found the behavior of the compiler here quite strange :

class A<P> {
    public p: P;
}

declare function test<P>(c: A<P> , p: P): P ;

interface Props { items: string }
test(new A<Props>(), {}); //no error no completion inside the 2nd object literal

I'm not so sure, but I think this behavior is different of 1.0, sure {} is a super type of { items: string } but I doubt that's what the developer is excepting here.

This is by the way preventing us from having correct inference for every factory like functions.

@fdecampredon fdecampredon changed the title Strange behavior in function type inferance Strange behavior in function type inference Feb 4, 2015
@RyanCavanaugh RyanCavanaugh added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Feb 4, 2015
@RyanCavanaugh
Copy link
Member

We have two candidates for P, one is a supertype of the other, so we choose the supertype. I don't see anything that distinguishes this from other cases where you'd definitely want the supertype chosen from among a set of candidates.

The only thing I can think of is that we could (could not would 😉) have a way to annotate that a use of a generic type parameter is not an inference site, e.g. you could say function test<P>(c: A<P>, p: ?P?): P); to say that the type of p should not be an inference candidate.

@fdecampredon
Copy link
Author

A bit sad :( I have everything working for jsx support in typescript but can't have type inference of jsx attribute because of that :p

React component defintion is more or less something like that :

interface Component <P> {
   props: P;
}
interface ComponentClass<P> { 
  new(props: P): Component<P>; 
  prototype: { props: P };
}

interface HTMLAttributes {
....
}
function createElement<P>(type: ComponentClass<P>, props: P, ...rest: any[]): something;
function createElement(type: string, props: HTMLAttributes, ...rest: any[]): somethingElse;

and for jsx:

<MyComponent attribute='something' />
//is equivalent of: 
createElement(MyComponent, { attribute: 'something' });

If someone think about a better way to define the types, or If you think about a way that I could have the correct inferred type in language service for the second argument, that could help ^_^.

@DanielRosenwasser
Copy link
Member

Just curious, is the idea that you desugar after parse-time into the call-form?

@fdecampredon
Copy link
Author

@DanielRosenwasser not really, I tried to fully implements support of JSX in the checker, I consider JSXElement as a CallLikeExpression and so implemented a resolveJSXElement don't know if it's the best way, see https://github.com/fdecampredon/jsx-typescript/blob/jsx/src/compiler/checker.ts#L6501-L6543, same goes for the JSXOpeningElement that is considered like an ObjectLiteralExpression, but with slight different rules etc etc ...

Anyway for JSXElement :
<MyComponent attribute='something' />
The emit is really
React.createClass(MyComponent, { attribute: 'something'})

I tried at first to consider the React.createClass as an implementation details and to directly type check JSXElement as the result type of this function :

{
  type: MyComponent
  props: {
    attribute: attribute,
    children: ...
  }
}

But it ended up to be very hackish since I had to create a lot of * fake node *, and since the type of children is recursive, in the end at least with the call form I have pretty good type checking.

@DanielRosenwasser
Copy link
Member

While this is where you get into territory that is extremely inconsistent with the rest of the language, you might want to experiment with the semantics of type argument inference with respect to JSX tags. It probably won't be easy to get correct, but, well, it could be fun!

@fdecampredon
Copy link
Author

Haha a little frightening :P, I think I'll start by finishing it correctly the way it is and perhaps I'll try that after ^^ thank you for your advice.

@Ciantic
Copy link

Ciantic commented Apr 8, 2015

Why not give a definition writer a possiblity to say which type is more specific?

declare function test<P>(c: A<P^> , p: P): P ;

I added the ^ to indicate this is where the P should be inferred. It could be a new syntax.

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

4 participants