Skip to content

Instantly share code, notes, and snippets.

@t0yv0
Last active February 28, 2021 01:47
Show Gist options
  • Save t0yv0/4449351 to your computer and use it in GitHub Desktop.
Save t0yv0/4449351 to your computer and use it in GitHub Desktop.
Demonstrating TypeScript 0.8 type system to be unsound. The subtyping relationship is defined in a way that admits the following code that results in TypeError exception being thrown.
Require Import Utf8.
Inductive subtype (a b : Set) : Set :=
| ST : (a -> b) -> subtype a b.
Infix ":>" := subtype (at level 50).
Definition st {x y} f := ST x y f.
Definition unpack {a b : Set} (st : a :> b) :=
match st with
| ST f => f
end.
Notation " x ~ y " := (unpack x y) (at level 50).
Definition sub_call {s x y} (p : s :> x) (f : x → y) : (s → y) :=
fun x => f (p ~ x).
Definition sub_ret {s x y} (p : s :> y) (f : x → s) : (x → y) :=
fun x => p ~ f x.
Definition sub_refl {a : Set} : a :> a :=
st (fun x => x).
Definition sub_fst {a b : Set} : (a * b) :> a :=
st (fun xy => fst xy).
Definition sub_snd {a b : Set} : (a * b) :> b :=
st (fun xy => snd xy).
Definition sub_fun {a b p q : Set} :
(p :> a) → (b :> q) → (a → b) :> (p → q) :=
fun g h => st (fun f x => h ~ f (g ~ x)).
Definition sub_fun_bad {a b p q : Set} :=
(a :> p) → (b :> q) → (a → b) :> (p → q).
Inductive empty : Set := .
Theorem empty_absurd : empty → False.
Proof. intro H. case H. Qed.
Definition fun_rule_absurd (r : sub_fun_bad) : False :=
let f (k : unit → empty) : empty := k tt in
let g (i : unit * empty) : empty := snd i in
empty_absurd (sub_call (r sub_fst sub_refl) f g).
class A {}
class B extends A {
foo(x: string) : string {
return x + "!";
};
}
function f1(k: (a: A) => void) : void {
k(new A());
}
function f2(k: (a: B) => void) : void {
f1(k);
}
f2(function (x: B) { console.log(x.foo("ABC")); });
@t0yv0
Copy link
Author

t0yv0 commented Jan 5, 2013

@valtron
Copy link

valtron commented May 31, 2013

Likewise, the generics are unsound: https://gist.github.com/valtron/5688638

@mindplay-dk
Copy link

I'm afraid I don't know the maths or language theory required to understand this, but is it any way related to what I posted here?

Are you arguing that TypeScript is fundamentally "unsound", by design, or are you saying it still needs work? (in your opinion, can it be fixed?)

Just wondering.

I've been using TypeScript on a smaller project, and I have been thrilled with the results - I realize it has problems, I ran into a few along the way, but overall, this was a much better experience than either JavaScript or C# ... it seems you get the type-checks, safety, scalability (in terms of complexity) and maintainability of C#, but only when you want it, and without breaking or inhibiting the dynamic features and "hackability" of JavaScript.

I don't know of any other language that attempts to do that. You guys know languages you would consider alternatives to TypeScript?

Thanks.

@relrod
Copy link

relrod commented Jun 6, 2015

@mindplay-dk This is two years late, but PureScript. :)

@TheSpyder
Copy link

I find the demonstration a bit easier to follow without the lambda:

class A {}

class B extends A {
  foo(x: string) : string {
    return x + "!";
  };
}

function f1(k: (a: A) => void) : void {
  k(new A());
}

function f2(x: B) {
  console.log(x.foo("ABC"));
}

f1(f2);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment