Nominal types versus structural types is basically the main distinction at this point (if we ignore .net, etc). I like both languages, happy to see them converge while keeping their defining characteristics
Here's a snippet of C# I wrote recently to transform some JSON:
var transformed = media.Select(m => {
var parts = m.Split('/');
return new {
addedAtUtc = "2023-05-15T05:59:31.398Z",
originTripUid = parts[4],
path = $"{parts[4]}/{parts[5]}",
rank = "",
size = 103978,
stored = true,
type = "document",
};
})
File.WriteAllText(
Path.Combine(Environment.CurrentDirectory, "output.json"),
System.Text.Json.JsonSerializer.Serialize(transformed)
);
It would be easy to mistake this as JS at a quick glance.Duck Typing at runtime is possible and to a degree checkable and compile-time.
var transformed = media.Select(m => {
var parts = m.Split('/');
return new {
addedAtUtc = "2023-05-15T05:59:31.398Z",
originTripUid = parts[4],
path = $"{parts[4]}/{parts[5]}",
rank = "",
size = 103978,
stored = true,
type = "document",
};
}).ToList();
transformed.AddRange(otherMedia.Select(m => {
var parts = m.Split('/');
return new {
addedAtUtc = "2023-05-15T05:59:31.398Z",
originTripUid = parts[4],
path = $"{parts[4]}/{parts[5]}",
rank = "",
size = 103978,
stored = true,
type = "document",
documentType = parts[6]
};
}));
Adding "documentType" breaks in C# but would work in a structurally typed language as a structural type checker can see that the second result fulfills all of the necessary properties. Doing this in C# would require creating an interface and being explicit.Function dispatch: TS is purely dynamic; C# has both static and dynamic
OOP: Mandatory in C#, optional in TS
Variance: Implicit in TS, explicit in C#
Numeric types: TS has one (number); C# has the entire signed/unsigned/float x 8/16/32/64-bit matrix
There's really no intentional effort to converge them.
[0]: https://www.typescriptlang.org/docs/handbook/2/everyday-type...