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

Strict Reflect.apply Reflect.construct and Function.prototype.apply/call/bind #33889

Open
5 tasks done
BlackGlory opened this issue Oct 9, 2019 · 6 comments
Open
5 tasks done
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@BlackGlory
Copy link

BlackGlory commented Oct 9, 2019

Search Terms

Reflect.apply
Reflect.construct
Function.prototype.apply
Function.prototype.call
Function.prototype.bind

Suggestion

These functions should not return any.

Related:
#212
#27028

Use Cases

function getString() {
  return 'string'
}

class ClassA {}

Reflect.apply(getString, null, []) // expected string but got any
Reflect.construct(ClassA, []) // expected ClassA but got any
Function.prototype.apply.call(getString, undefined) // expected string but got any
Function.prototype.call.call(getString, undefined) // expected string but got any
Function.prototype.bind.call(getString, undefined)() // expected string but got any

Examples

Reflect:

// old
function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;

// new
function apply<T>(target: (...args: any) => T, thisArgument: any, argumentsList: ArrayLike<any>): T;

// old
function construct(target: Function, argumentsList: ArrayLike<any>, newTarget?: any): any;

// new
function construct<T>(target: new (...args: any) => T, argumentsList: ArrayLike<any>, newTarget?: any): T;

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
    👆 Add a new compiler option
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@jablko
Copy link
Contributor

jablko commented Oct 9, 2019

I'd expect Function.prototype.apply(null, getString); to error, like (Function.prototype as CallableFunction).apply(null, getString);:

error TS2684: The 'this' context of type 'CallableFunction' is not assignable to method's 'this' of type '(this: any, ...args: any[]) => unknown'.
  Type 'CallableFunction' provides no match for the signature '(this: any, ...args: any[]): unknown'.

--stringBindCallApply should apply the CallableFunction interface to the Function global as well as to function instances?

@BlackGlory
Copy link
Author

The original use case code has an error and has been fixed.

Since Reflect.apply is easier to use than Function.prototype.apply and Reflect.construct provides feature that Function.prototype does not have, maybe we don't need to apply CallableFunction interface to Function, we just need to improve Reflect.apply and Reflect.construct.

@jablko
Copy link
Contributor

jablko commented Oct 10, 2019

Just checking whether the spread operator available to you?

const args = [];
new ClassA(...args); // ClassA

@BlackGlory
Copy link
Author

This is not an issue about how to dynamically create an object instance.

@jablko
Copy link
Contributor

jablko commented Oct 11, 2019

Would you consider adding more information about your use case?

@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Oct 17, 2019
@zanminkian
Copy link

zanminkian commented Sep 16, 2024

This issue is equivalent to say: add type guard for Reflect.apply under --strictBindCallApply.

Example:

function foo(name: string) {
  console.log(name)
}

foo.apply(null, [42]); // typescript will report type error, great!
Function.prototype.apply.call(foo, null, [42]); // no error 😢
Reflect.apply(foo, null, [42]); // no error 😢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants