sirisian / ecmascript-types

ECMAScript Optional Static Typing Proposal http://sirisian.github.io/ecmascript-types/
453 stars 4 forks source link

Syntax for typing the returned array or object used with destructuring #40

Open sirisian opened 6 years ago

sirisian commented 6 years ago

In cases where an array where all values are identical are returned the typing is easy:

function F():uint8[]
{
    return [1, 2, 3];
}
const [a, b, c] = F(); // a, b, and c are uint8

However with destructuring it's common to return a mix of types utilizing arrays or objects to hold the items. One might think of the syntax:

function F():[uint8, uint32, uint64]
{
    return [1, 2, 3];
}
const [a, b, c] = F(); // a is uint8, b is uint32, and c is uint64
function F():{uint8, uint32, uint64}
{
    return { a: 1, b: 2, c: 3 };
}
const { a, b, c } = F(); // a is uint8, b is uint32, and c is uint64

I can't pin down where the issues are but it seems like there probably are issues with this syntax direction. Maybe I'm overthinking it. More complex objects might need to be analyzed. It's possible to make some complex return statements.

This might be easier to accept if TS interfaces were added.

sirisian commented 6 years ago

Would the [uint8] syntax conflict with https://github.com/sirisian/ecmascript-types#multidimensional-and-jagged-array-support-via-user-defined-index-operators

In that part of the spec I don't mention typing the index value of an any array.

let foo:[int32] = [1, 2, 3];

I guess in that use case it's not a return value so there's no conflict. We'd be analyzing functions:

function F():[int32]
{
    return [1];
}

So staying consistent with the typed array syntax this would indicate an any array with an index of type int32. It wouldn't even make sense to look at it like it was defining the types of the destructed values.

We can be consistent with the destructuring syntax: https://github.com/sirisian/ecmascript-types#destructuring-assignment-casting

function F():[:int32]
{
    return [1];
}

By putting :int32 we tell it that we're specifically typing the element. We can type the index also:

function F():[int32, :int32]
{
    return [1];
}

An example with two elements typed:

function F():[int32, :int32, :float32]
{
    return [1, 2.0];
    // return [1]; // TypeError?
}

Might have to cover optional values and new syntax depending on the goals. This could be overloaded it would seem at least for the number of returned elements.

function F():[:int32]
{
    return [1];
}
function F():[:int32, :int32]
{
    return [2, 3];
}
const [a] = F();
const [a, ...b] = F(); // a is 2 and b is [3]

This brings into question if ...n syntax is useful to skip arguments. Not important, and probably wouldn't conflict.

TODO: Create object examples.

sirisian commented 6 years ago

Examples to think about. Basic typed object return:

function F():{ (a:uint8), (b:float32) }
{
    return { a: 1, b: 2 };
}
const { a, b } = F(); // { a: 1, b: 2 }

Is it meaningful to have renaming and defaults?

function F():{ (a:uint8): c, (b:float32) = 10 }
{
    return { a: 1 };
}
const { c, b } = F(); // { c: 1, b: 10 }

Seems useful to create a complete spec that defines all possible syntax. These examples cover probably all that one might expect to be possible given previous syntax.

sirisian commented 6 years ago

I have to say that I dislike the [:int32] syntax. There has to be a better way to do things. Ideally I'd want to write:

function F():[int32, int64]
{
    return [2, 3];
}

It seems intuitive that for uses with destructuring that the type of the length of the returned array doesn't matter. It's basically a special array.

The solution to solve this would be to rethink how the length type is defined for arrays. That syntax was always rather ad-hoc anyways.

const foo = new uint8[]<int64>;
const foo = new uint8[:int64];

No idea. Does need to be changed though to get a more ideal syntax.

sirisian commented 6 years ago

Added changes to the proposal: https://github.com/sirisian/ecmascript-types#typed-return-values-for-destructuring

Also changed the array length type syntax to use [:uint32] syntax.

Now I need syntax for optional object properties.

Also I'm really considering adding syntax for interfaces and their associated usage. TODO: Add examples.