Live data from Hacker News

Making sense of TypeScript using set theory

blog.thoughtspile.tech

71–80 of 94 posts

Re: Making sense of TypeScript using set theory

#71

Earlier quoted context omitted.

Nope. This is a common confusion. The set of properties of objects and the sets of objects themselves have a complementary relationship when it comes to union / intersection and subset / superset. Let's define a "property" as being a predicate that is true for all elements of a set. For example, a collection of red objects has the "red" property. A subset of a set of objects can only have the same or more properties…

I think that interfaces in TypeScript unfortunately contribute to that confusion. I can do interface Point2D { x: number y: number } And then I can do interface Point3D extends Point2D { z: number } And that "extends" really throws off many people because in reality the type of Point2D is implicitly { x: number y: number [anything_else in string]: unknown } So Point3D actually narrows the type of Point2D even though…

> So Point3D actually narrows the type of Point2D even though the notation suggests that it widens it.

The notation suggests that it extends the definition with additional restrictions. Which it does. Which, yes, produces a narrower scope. That’s how definitions work.

Re: Making sense of TypeScript using set theory

#72

Earlier quoted context omitted.

The way "subset of properties" is being used here is loose and that's where the confusion is arising from. If we want to be a bit more rigorous: * Define O as a set of possible (finite) objects * Define properties as functions P: O -> {0, 1} * A given property then is a function of the form p(o) = 1 for all o in O that satisfy the property p. You can use property functions to generate subsets of O ({ o for o in O whe…

Thanks for that, it makes sense using your definition. I'm curious as to whether you agree with the parent comment that the subset could contain 'more' properties than the superset. My understanding from your stricter definition is that (by definition) all potential properties (o for o in O where p(o) = 1) must be contained within O. If the answer is that the superset O has fewer properties where every p(o) = 1 then…

> If the answer is that the superset O has fewer properties where every p(o) = 1 then I agree, and I was overthinking it

It's just this honestly. A superset will generally have fewer properties which apply across the whole set.

Re: Making sense of TypeScript using set theory

#73
post #24

I might be missing something, but isn't this line backwards? > Subtype of type A is a subset of type A. Supertype is a superset. Easy. Subtype of type A is actually a superset of type A, since it contains at least all the properties of A. If you had (contrived example) a Dog class that inherited from an Animal class, Dog would be a sub type of Animal, but its additional properties (say, a bark() method) mean that it…

> 4. A extends B ... can be read as "A is subset of B". I agree, it is unnatural to think of a subset as "extending" the set it is part of.

Yeah, it's a common way of telling people how to read "A extends B", but it's not quite right. The two relationships are related (no pun intended) but they aren't the same relationship. `A extends B` means (in the OO world) that A adds fields, methods, or changes the behavior of methods to B. `A is a subset of B` means that all As are Bs, but some Bs may not be As.

It happens that `A extends B` introduces a subset relation between them, but it's not correct to describe it as the same as the subset relation.

Re: Making sense of TypeScript using set theory

#74

Earlier quoted context omitted.

Nope. This is a common confusion. The set of properties of objects and the sets of objects themselves have a complementary relationship when it comes to union / intersection and subset / superset. Let's define a "property" as being a predicate that is true for all elements of a set. For example, a collection of red objects has the "red" property. A subset of a set of objects can only have the same or more properties…

I think that interfaces in TypeScript unfortunately contribute to that confusion. I can do interface Point2D { x: number y: number } And then I can do interface Point3D extends Point2D { z: number } And that "extends" really throws off many people because in reality the type of Point2D is implicitly { x: number y: number [anything_else in string]: unknown } So Point3D actually narrows the type of Point2D even though…

"Extends" does not mean it extends the type to contain more members, it means it extends instances to have more properties, thereby creating a subset or subtype.

Perhaps it is confusing that TypeScript uses terms from both set-theory (union, intersection) and OO (extends, implements). But there is no contradiction.

Re: Making sense of TypeScript using set theory

#75

Earlier quoted context omitted.

I think that interfaces in TypeScript unfortunately contribute to that confusion. I can do interface Point2D { x: number y: number } And then I can do interface Point3D extends Point2D { z: number } And that "extends" really throws off many people because in reality the type of Point2D is implicitly { x: number y: number [anything_else in string]: unknown } So Point3D actually narrows the type of Point2D even though…

> So Point3D actually narrows the type of Point2D even though the notation suggests that it widens it. The notation suggests that it extends the definition with additional restrictions . Which it does. Which, yes, produces a narrower scope. That’s how definitions work.

In mathematical logic, for example, saying that A is an elementary substructure of B is equivalent to saying that B is an elementary extension of A. The same with subfields and extension fields. Those concepts are opposite.

Usually in OOP you extend a class with additional implementation. Intersection of types means union of their members and vice versa. Getting into a situation where extending X gives you a sub-X seems like an unfortunate case of mixing two mental models that behave in a dual manner.

Re: Making sense of TypeScript using set theory

#76
post #41

Earlier quoted context omitted.

Because Typescript is designed to accept any valid Javascript program, the set of valid statements in a Typescript program is a superset of the set of valid statements in a Javascript program. Typescript contains all the rules of Javascript, and then adds some more, but never in a way that contradicts the requirement that a plain Javascript program should compile, so that also means the language specification itself…

Here are 3 statements that were made in this thread: - typescript is a superset of javascript - superset of objects can only have the same or fewer properties - Typescript contains all the rules of Javascript, and then adds some more Do you see where the confusion is coming from? > that also means the language specification itself is a strict superset of Javascript This is where I disagree. TS as a language has more…

TypeScript is a superset of JavaScript because any JavaScript program is also a Typescript program but not vice versa. There is no contradiction.

> TS as a language is a superset of JS language. TS as a spec is a rough subset of JS spec.

This does not make any sense. A spec which fully describes TypeScript including runtime behavior would include the JavaScript spec and therefore be a superset. The TypeScript spec itself is in no way a subset of the JS spec, sine it descries features and syntax which does not exist in vanilla JavaScript.

Re: Making sense of TypeScript using set theory

#77
post #74

Earlier quoted context omitted.

I think that interfaces in TypeScript unfortunately contribute to that confusion. I can do interface Point2D { x: number y: number } And then I can do interface Point3D extends Point2D { z: number } And that "extends" really throws off many people because in reality the type of Point2D is implicitly { x: number y: number [anything_else in string]: unknown } So Point3D actually narrows the type of Point2D even though…

"Extends" does not mean it extends the type to contain more members, it means it extends instances to have more properties, thereby creating a subset or subtype. Perhaps it is confusing that TypeScript uses terms from both set-theory (union, intersection) and OO (extends, implements). But there is no contradiction.

Right, my point is that it is confusing.

Re: Making sense of TypeScript using set theory

#78

I might be missing something, but isn't this line backwards? > Subtype of type A is a subset of type A. Supertype is a superset. Easy. Subtype of type A is actually a superset of type A, since it contains at least all the properties of A. If you had (contrived example) a Dog class that inherited from an Animal class, Dog would be a sub type of Animal, but its additional properties (say, a bark() method) mean that it…

Nope. This is a common confusion. The set of properties of objects and the sets of objects themselves have a complementary relationship when it comes to union / intersection and subset / superset. Let's define a "property" as being a predicate that is true for all elements of a set. For example, a collection of red objects has the "red" property. A subset of a set of objects can only have the same or more properties…

This depends on what you mean by "property".

Universal properties are preserved "downwards" i.e. in subsets (more properly, substructures). Existential properties are preserved upwards, i.e. in supersets (extensions).

For example, the property "there exists an element that equals itself when added to itself" is preserved in a superset.

If you have sentences that mix quantifiers (e.g. "for all epsilon, there is a delta ..." or even just "every element has an inverse"), then all bets are off.

The branch of mathematics where this is studied (and rigorously proven) is model theory.

edit: I guess by "property" (given the context of the discussion) you might just mean "function" or "method", in which case, yes, a function defined on a set is also defined on a subset but not necessarily vice versa, so there are in a certain sense "more" functions defined on the subset.

Re: Making sense of TypeScript using set theory

#79
post #48

Earlier quoted context omitted.

You're making this harder than it actually is by conflating a bunch of things, comparing apples and oranges. Sets defined by type vs sets defined by lists of properties, specs, rules etc. For types, just draw the Venn diagrams: - The set of objects of Type A is entirely within the set of objects of Subtype of A. Subtype of A is the superset. - the set of things that are Dogs (class or real world) is entirely within t…

> Sets defined by type vs sets defined by lists of properties, specs, rules etc. Recursive explanations are useless: "types are just sets defined by types". That's why we are trying to define them through other means. Also TS has structural type system, which is literally about comparing properties.

That's not what GP wrote - they wrote that there is a difference between "the set of all instances of type A" and "the set of all properties satisfied by all instances of type A". There's nothing recursive about that. And this is all completely independent of the question of whether a language is structurally or nominally typed.

Re: Making sense of TypeScript using set theory

#80
post #30

Having set types like this and refining them smaller is something I wish Haskell would learn from Typescript, especially the automatic inference side. I wonder if it would help with linear types? Are there any proposals? I know there are type level naturals in the type system, but this is more like wanting to deconstruct existing types like Int or String into subset types. e.g., foo :: Int -> 3::Int | 4::Int foo 4 =…

> Having set types like this and refining them smaller is something I wish Haskell would learn from Typescript, especially the automatic inference side Haskell has far better type inference than Typescript in large part because it doesn't have subtyping. There are libraries for open records and sums (e.g. https://hackage.haskell.org/package/vinyl ) but they're almost always the wrong choice.

> Haskell has far better type inference than Typescript in large part because it doesn't have subtyping.

That's a bit like saying "Go has a faster compiler because the language is so simple". It's true, but there's a genuine tradeoff here.

Haskellers have convinced themselves that subtypes are not worth it - and they may be right in many cases - but subtyping is a quite natural way of modeling many concepts (for example: mathematical expressions). Some of that can be recovered by typeclasses, existential types and other machinery (or you could go as far as dependent types), but that seems all more cumbersome and hard to understand than the way subtyping works in languages that support it out of the box.

Post reply on HN