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

Pass Template Arguments to Function #25585

Closed
3 of 4 tasks
laurayco opened this issue Jul 11, 2018 · 3 comments
Closed
3 of 4 tasks

Pass Template Arguments to Function #25585

laurayco opened this issue Jul 11, 2018 · 3 comments
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints

Comments

@laurayco
Copy link

laurayco commented Jul 11, 2018

Search Terms

  • "template value"
  • "static template interfaces"
  • "generic static properties"

Suggestion

Presently generics in Typescript only mean something to the typescript compiler and the generated code isn't able to take advantage of them. I realize why this is, but I think there is a missed opportunity here. It would be nice if (where possible!) an actual data member variable were created according to the generic variable name. ie:

function generic_add<T>(a: T, b:T): T {
  return a + b;
}

would become:

function generic_add_T(T,a,b) {
  return a + b;
}

function generic_add(a,b) {
   const T = a.__proto__.constructor; // in current chrome this works for function and class types.
   generic_add_T(T,a,b);
}

In the case that an Interface is passed as an argument (which has no existing run-time value) an argument should not be created. To help enforce this, a slightly different syntax:

interface IUsefulMethods {};

// this can only be called where T is a type with a static implementation
// of IUsefulMethods, which would imply that T is a type with a run-time value
// so we would pass T as a hidden(to typescript) parameter
function generic_add<T: IUsefulMethods>(a: T, b:T): T {
  return a + b;
}

// T has no restrictions or declared interfaces
// no guarantee that it has a run-time value
// so we don't pass T as a hidden parameter.
function generic_sub<T>(a: T,b:T) : T {
}

Use Cases

This would allow us to make generics actually useful in typescript beyond type-checking. If we can specify that a template argument extends from another type, then we should be able to access that type's static members.

Examples

This script:

interface StaticInterface {
   static_method(a: number) : number;
}

class Shape {
  useful_number : number;
}

class SquareEntity {
   static static_method(a: number) : number { return a * a; }
}

class CircleEntity {
   static static_method(a: number) : number { return 3.14 * (a * a); }
}

function calculate_area<ObjectShape extends Shape>(iface: StaticInterface, shape: ObjectShape) {
   return iface.static_method(shape.useful_number);
}

Would be more readable like this:

interface StaticInterface {
  static_method(a: number) : number;
}

class Shape {
   useful_number: number;
}

class SquareEntity extends Shape {
   static static_method(a: number) { return a*a; }
}

class CircleEntity {
   static static_method(a: number) { return 3.14 * (a*a); }
}

function calculate_area<T extends Shape: StaticInterface>(shape: T){
  return T.static_method(shape.useful_number);
}

The usefulness is more obvious when using this code:

Current:

const square = new Square;
square.useful_number = 4;
calculate_area<Square>(Square,square);

Proposed:

const square = new Square;
square.useful_number = 4;
calculate_area<Square>(square);

Checklist

I'm not sure what "based on the types of the expressions" means but this new syntax wouldn't introduce or attempt to introduce new JS syntax or type specialization code (as in emitted code that behaves differently depending on the type that is passed in).

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • This isn't a runtime feature (e.g. new expression-level syntax)
  • 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
@laurayco
Copy link
Author

laurayco commented Jul 11, 2018

Note:

Thinking about it and this is viable for projects that execute all of their own generic code but if javascript tries to make use of output generic code it would need knowledge of the generics. If we try to infer the type from .__proto__.constructor, then there's the possibility of the generic instance being null which is not ideal and in the case where there are no generic instances not possible at all and instead typescript would need to use an actual parameter and pass in the values for the parameter automatically. I think the solution where typescript automatically creates hidden parameters and fills them out according to the function call is ideal and then just expect users to read typescript documentation on a typescript project but this is one issue I see being troublesome.

@mhegazy
Copy link
Contributor

mhegazy commented Jul 11, 2018

Runtime type system support is something that remains outside the scope of the TypeScript project. Please see the TypeScript design goals (https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).

Please see #2444, #3314, #3442 and #1573 for similar requests.

@mhegazy mhegazy added the Out of Scope This idea sits outside of the TypeScript language design constraints label Jul 11, 2018
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints
Projects
None yet
Development

No branches or pull requests

3 participants