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 is a strict superset of Javascript.
With these declarations your fragment is valid in both JavaScript and TypeScript:
class b {}
class c {}
const d = JSON.parse
const a = Promise.prototype.then.bind(Promise.resolve(1))
console.log(a<b,c>(d))
// TS output: Promise { <state>: "pending" }
// JS output: false false
It is strictly true. a<b,c>(d) is only valid JavaScript iff a, b, c, and d are values.
The TypeScript expression a<b,c>(d) where b and c are types is NOT JavaScript, since JavaScript doesn't have type expressions. The statement that every JavaScript program is a valid TypeScript program does not imply the opposite - hence strict superset.
edit: there is indeed an edge case with the parentheses that throws the TypeScript parser off even if only values are involved.
See the sibling comment from oblosys for an example where the exact same code can give different results in vanilla JS vs after a tsc pass. As you can see there, the problem is that an identifier can simultaneously represent a value and a type.
This is different than JSX or hashbang, where the set of non-JS syntax cannot legally overlap with existing syntax/semantics.
I guess this is a distinction between intent and results. Typescript is intended to be a strict superset of Javascript. In practice, there are edge cases like these.
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 properties than JS, but less rules. I.e. you can create Javascript language out of Typescript by adding more rules (constraints).
But TS as a spec has more rules than JS spec.
TS as a language is a superset of JS language. TS as a spec is a rough subset of JS spec.
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 the set of things that are Animals.
- the set of things that are Javascript programs is entirely within the set of things that are Typescript programs.
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.
It's recursive in the context of "making sense of TS using set theory". If you understand sets, but not types, statements about "sets defined by types" are meaningless.
> superset of objects can only have the same or fewer properties
This is potentially misleading. A superset will include more objects and therefore may include more individual properties. But type checking is about what can be safely assumed about all members of a set, so more different objects in the set will constrain the type more.
Object is a superset of Date because the set of objects includes alle Dates but also things which are not dates and have different properties. But in the context of type checking, object is more constrained because there are fewer properties which all members of the set are guaranteed to have.
Typescript is a superset of Javascript because all Javascript programs are also Typescript programs. There is no contradiction.
> object is more constrained because there are fewer properties which all members of the set are guaranteed to have.
In my mind it's the opposite: object is less constrained, because there are fewer requirements you need to fulfill to be considered an object. Object type is very permissive.
The more constrained type is, the fewer objects it's set will contain. The more constrained the type is, the more rules it enforces. Seems intuitive, isn't it?
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.
This is how you should think about it: Spec > Language > Code.
Code is an instance of Language (and in structural typing land it can be compatible with multiple languages). Language is an instance (implementation) of Spec.
> sine it descries features and syntax which does not exist in vanilla JavaScript
That's exactly why TS spec is a subset. Take example from the article:
type B = true extends boolean ? 1 : 0; // 1
Type B is a subset of boolean, meaning there are less objects in the world that satisfy type B.
There are less language implementations in the world that satisfy TS spec than JS spec. Every language that satisfies TS spec also satisfies JS spec. TS spec adds more constraints (requirements) to language implementation compared to JS spec, it is more strict, therefore it's a subset.
So you are saying the implementation of the Typescript language are a subset of all JavaScript implementations? I guess that is true in a certain sense. But this does not contradict the fact that TypeScript as a language is a superset of JavaScript - rather it follows logically.
(Although in reality the Typescript implementation is a preprocessor, intended to use together with a regular JavaScript engine.)
Kind of. The language gets confusing because we use subset and superset next to each other, but we put different meaning on them.
{foo: number, bar: string} as type is a subset of both {foo: number} and {bar: string}. It requires it's members to have both properties. You can construct this type using intersection:
type Foo = {foo: number}
type Bar = {bar: string}
type FooBar = foo & bar
{foo: 1, bar: 'hello'} as object is a superset of {foo: 1} and {bar: 'hello'}. It contains both properties. We can construct this object using union (I use pipe instead of spread to illustrate the idea):
let foo = {foo: 1}
let bar = {bar: 'hello'}
let foobar = foo | bar
When I'm saying TS is a superset of JS, I mean it in the object sense. It has all the properties of JS, and some more. All JS programs are also TS programs, but not vice versa. There's more JS programs in the world than TS programs.
When I'm saying TS spec is a subset of JS spec, I mean it in a type sense. Language is an instance of a spec. TS spec has all of the requirements of JS spec, and some more. All TS implementations (languages) will contain JS implementations, but not vice versa. There's more JS implementations in the world, than TS implementations (assuming you can build TS as compiler/interpreter instead of transpiler).
In any case, the TS spec is a superset of the JS spec, since it incorporates the JS spec. If you don't consider the JS spec as part of the TS spec then they are disjoint sets. But the TS spec cannot be a subset of the JS spec since that would mean it removed some parts of the JS spec, which is not the case.
Because all valid JS code is also valid TS code (considering implicit any). Or, put another way, the set of all valid JS programs is a subset of all valid TS programs.
and this is your response? did you come up with extremely clever reduction in the shower and wait for the first post that's tangentially relevant (and in fact embodies the opposite of what you're attacking?)
https://en.wikipedia.org/wiki/TypeScript