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

generic rest parameters #101

Open
maiermic opened this issue May 14, 2016 · 3 comments
Open

generic rest parameters #101

maiermic opened this issue May 14, 2016 · 3 comments
Labels

Comments

@maiermic
Copy link

As mentioned in #96 we can describe generics that take an indefinite number of type arguments using rest parameter syntax:

interface Collection[...T] {
  // use rest parameters to describe Collection interface 
}

But how can we access a specific type (argument) of the passed rest arguments?

@maiermic
Copy link
Author

maiermic commented May 14, 2016

Say Collection[Number, String, Boolean] should for example be equal to the interface

{
  0: Number,
  1: String,
  2: Boolean,

  length: Number
}

We can calculate this type using a JavaScript function

function CollectionType(types) {
  var collectionType = {};
  for (var t in types) {
    collectionType[t] = types[t];
  }
  return collectionType;
}

and define

interface Collection[...T] {
  ...(CollectionType(T)),
  length: Number
}

How is Collection[Number, String, Boolean] calculated?

Number, String and Boolean are passed to Collection[...T]. Since T is a rest parameter T is an array [Number, String, Boolean]. Let's substitute

{
  ...(CollectionType([Number, String, Boolean])),
  length: Number
}

apply CollectionType

{
  ...({ 0: Number, 1: String, 2: Boolean }),
  length: Number
}

apply the spread operator and we get the intended interface

{
  0: Number,
  1: String,
  2: Boolean,

  length: Number
}

Note: This introduces dependent types.

How can we describe types with an indefinite number of actual type arguments like Collection[Number, String, ...Boolean]? The equivalent interface has an indefinite number of properties.

@maiermic
Copy link
Author

How can we describe types with an indefinite number of actual type arguments like Collection[Number, String, ...Boolean]?

Collection[Number, String, ...Boolean]

is equal to

{
  ...Dictionary[Number, Boolean],
  0: Number,
  1: String,

  length: Number
}

Note: See #99 for definition of Dictionary[Key, Value].

Since ...Boolean is a special type argument that represents 0 or more type arguments Boolean it has to be represented as special value to be distinguishable. I will introduce a new built-in type

interface Spread[T] {
    type: T
}

to describe ...Boolean as Spread[Boolean].

Now we can define Collection interface as

interface Collection[...T] {
  ...(RestElements(T))
  ...(CollectionType(T)),
  length: Number
}

where

function CollectionType(types) {
  var collectionType = {};
  for (var t in types) {
    if (!isSpread(types[t])) { // exclude spread type argument
      collectionType[t] = types[t];
    }
  }
  return collectionType;
}

function RestElements(types) {
  if (types.length > 0) {
    var lastType = types[types.length - 1];
    if (isSpread(lastType)) {
      return Dictionary(Number, lastType.type);
    }
  }
  return {};
}

function isSpread(type) {
  return type instanceof Spread;
}

@ericelliott
Copy link
Owner

I like Collection[Number, String, ...Boolean] in the context of #120. Does this proposal need revision?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants