question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Writing types in JavaScript instead of TypeScript

See original GitHub issue

Okay, so I’ve been pondering (and talking to @axefrog). If TypeScript’s type system itself is turing complete and that offers great opportunities, why are we writing the types in this stunted turing tarpit language, instead of writing the types themselves in JavaScript too? Here’s the idea: you write a program, that when run, outputs itself without the type annotations. This is exactly like what TypeScript does, but in this case, the input is JavaScript, the output is JavaScript and the original JavaScript is both the source and the compiler at the same time (running the program is compilation, the output is the stripped version).

Here’s what that would look like:

import { Type, isType } from "js-types";

// Record definition

const Complex = {
    real: Number,
    imaginary: Number
}

// Function definition

const ComplexMult = (a, b) => {
    if (isType(a, Number) && isType(b, Number)) {
        return Number;
    } else {
        throw TypeError();
    }
};

Type(
    ComplexMult,
    function mult(a, b) {
        return {
            real: (a.real * b.real) - (a.imaginary * b.imaginary),
            imaginary: (a.real * b.imaginary + a.imaginary * b.real)
        };
    }
);

// Alternate ways to write the definition:

const ComplexMultAlt1 = (a, b) => {
    if (isType({ a, b }, { a: Number, b: Number })) {
        return Number;
    } else {
        throw TypeError();
    }
};

// With arrays instead of objects:

const ComplexMultAlt2 = (a, b) => {
    if (isType([a, b], [Number, Number])) {
        return Number;
    } else {
        throw TypeError();
    }
};

// Helper definition, notice it returns a function

const Func = (inputTypes, outputType) => {
    return (...inputs) => {
        if (isType(inputs, inputTypes)) {
            return outputType;
        }
        else {
            throw TypeError();
        }
    };
};

// With this helper, we could've done this:

Type(
    Func({ a: Complex, b: Complex }, Complex),
    function mult(a, b) {
        return {
            real: (a.real * b.real) - (a.imaginary * b.imaginary),
            imaginary: (a.real * b.imaginary + a.imaginary * b.real)
        };
    }
);

// Example of function returning function, very simple

Type(
    Func(Complex, Func(Complex, Complex)),
    function add(a) {
        return (b) => ({
            real: a.real + b.real,
            imaginary: a.imaginary + b.imaginary
        });
    }
);

// Generics, again, super simple

const IdentityFunction = a => a;

Type(
    IdentityFunction,
    function identity(a) {
        return a;
    }
);

// Variadic kinds
// Note that f would also be a type-checking function
// when it comes in

const CurryFunction = (f, ...a) => {
    if (isType(f, Function)) {
        return (...b) => f(...a, ...b)
    }
    else {
        throw TypeError();
    }
};

Type(
    CurryFunction,
    function curry(f, ...a) {
        return (...b) => f(...a, ...b);
    }
);

And here’s the output of running that program:

function mult(a, b) {
  return {
    real: a.real * b.real - a.imaginary * b.imaginary,
    imaginary: a.real * b.imaginary + a.imaginary * b.real
  };
}

function add(a) {
  return b => ({
    real: a.real + b.real,
    imaginary: a.imaginary + b.imaginary
  });
}

function identity(a) {
  return a;
}

function curry(f, ...a) {
  return (...b) => f(...a, ...b);
}

I know this is quite the silly idea, but I think there’s merit to it. As you can see, the sample seems to indicate it can easily type a curry function, something that is apparently quite hard in TypeScript.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:14 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
SimonMeskenscommented, Nov 16, 2017

My example was very crude, if I manage to hook into the TS system, you’d still be able to throw decent errors of course. And yeah, I agree that with just JS types, that might be a serious step backwards from what we have now (even with a good inference engine).

I think the next step is for me to put the money where my mouth is and provide a PoC, so we can further discuss merits 😃

And yeah, I keep wanting to play around with tcomb and schemas, I should do that at some point.

0reactions
KiaraGrouwstracommented, Feb 17, 2018

I’m gonna mark closed in the sense of ‘not actionable within the scope of this lib’. Discussion though is always welcome.

Read more comments on GitHub >

github_iconTop Results From Across the Web

TypeScript vs. JavaScript: Your Go-to Guide - Toptal
TypeScript is better than JavaScript in terms of language features, reference validation, project scalability, collaboration within and between teams, developer ...
Read more >
TypeScript vs JavaScript – Difference Between Them - Guru99
TypeScript is a modern age JavaScript development language whereas JavaScript is a scripting language which helps you create interactive web ...
Read more >
TypeScript: JavaScript With Syntax For Types.
TypeScript is JavaScript with syntax for types. TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at ......
Read more >
TypeScript vs JavaScript: Which One Should You Choose?
TypeScript is a strongly typed, object-oriented programming language, whereas, JavaScript is a programming language for the web.
Read more >
TypeScript vs. JavaScript: 7 Key Differences - Sanity.io
While JavaScript is dynamically-typed, TypeScript is a statically-typed superset of JavaScript, which means it offers strict static typing as ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found