Earlier quoted context omitted.
You can directly import any valid JS module using TypeScript if you have “allowJS”: true in the compiler options of your tsconfig.json file. The comparison to FFI doesn’t make any sense. FFI requires compiling a special library that explicitly exports the C types. This is different than TS. Using TS, you can import any valid JS module without any special preparation. Also, you can’t import all compiled languages into…
>There is no way to export a Go struct for consumption via FFI, for instance. I hope not. >Using TS, you can import any valid JS module without any special preparation Why does the DTS ecosystem exist then ( https://www.npmjs.com/package/@types/node etc)
TypeScript is now officially 10 years old
161–170 of 207 posts
Re: TypeScript is now officially 10 years old
#162Earlier quoted context omitted.
The verbosity of TypeScript types can be attributed to poor choice of syntax and names that became obvious retrospectively. Still even with TypeScript if types makes your functions ugly, then it shows the complexity of the code. Often it also suggests sensible refactoring that without types would not be apparent.
Typscript: "function area(left: number, top: number, right: number, bottom: number): number {" Javascript: "function area(left, top, right, bottom)" In an editor the typescript function would likely be split into five separate lines. "function area( left: number, top: number, right: number, bottom: number) : number {" None of the functions are complex but the the typescript function with the formatter creates a lot o…
It also means it's not going to explode when fed the wrong types, because that's not possible.
Re: TypeScript is now officially 10 years old
#163Earlier quoted context omitted.
Character input time is a vanishingly small concern for overall productivity. If it's a concern then you'll probably catch more bugs by slowing down to think.
Typing it is not the problem. It is reading at a glance that becomes much harder since lines oftentimes get split into multilines. I get less of an overview.
If there are so many parameters that it falls out of mental context then there's too many parameters.
Re: TypeScript is now officially 10 years old
#164Earlier quoted context omitted.
You’re right on the first (although classes are out of fashion, so this is low impact) On the second, doesn’t this work?: ‘function foo({ bar = 3 }: { bar?: number })’
>You’re right on the first Strictly speaking, it takes exactly one such behavior (that you cannot even disable) for TS to stop being a superset of JS. >although classes are out of fashion, so this is low impact Looking at the TSC codebase, so are keyword arguments. The "in" thing is just to write very very long lines of multiple verbosely named positional arguments instead. That said, "clases are out of fashion" is a…
Huh? I’m of the functional persuasion too, and I use classes in TS too, but for strategic reasons (well defined value objects are easier to reason about than duck typed POJOs, and they perform better too). But I’ve never found them more space-dense than the equivalent function-only code. Often quite the opposite, as so many functions’ return types can be fully inferred. Which of course, this is how you get ~~ants~~ duck typed POJOs, but you can’t have explicit type defs without explicit defining them somewhere, and of course the syntax that collocates the field type and its value is more dense than the syntax which is wholly incompatible with that concept.
> handling of default property values and "definedness" differs
The only difference is that TS provides a fully optional shorthand for assigning both the type and value in constructor arguments. The actual behavior isn’t any different. This:
class Foo {
constructor(readonly bar: number) {}
}
is identical to: class Foo {
readonly bar: number;
constructor(bar: number) {
this.bar = bar;
}
}
is identical to: class Foo {
bar;
constructor(bar) {
this.bar = bar;
}
}
And this type error: class Foo {
readonly bar: number;
constructor(bar: number) {}
}
is identical to this type error, just caught sooner: class Foo {
bar;
constructor(bar: number) {}
}
const foo = new Foo();
foo.bar.toFixed(2);
> Sure, the constructor signature may change in a subclass (why not disallow incompatible constructor overrides, given incompatible property/method signatures are already disallowed?)Because the compatibility is checked on the `super` call which is required both at compile time and runtime, and because many use cases for subclasses are impossible or even invalid without different construction contracts.
I know there are many strong feelings about examples like this being “wrong”, but it’s a common enough inheritance example to illustrate the point:
class Square extends Rectangle {
constructor(/* ? */) {}
}
You cannot satisfy both Square and Rectangle with the same constructor arguments. This of course bolsters the point that this inheritance model is “wrong”, but it’s exactly right according to the domain, and the equivalent functional code to calculate eg area would similarly have to be either polymorphic over different shapes or expect a single shape constructed with different parameters.> this.constructor
You got this one right, and it’s worse than you describe because of the weird rules for where you can’t have type parameters or explicit `this` types. The workaround is to use a static factory method, but it’s a shitty workaround with a lot of ceremony to do something that TS generally does well: model the types of real world JS code.
> Also crap like not being able to have a question mark and a default value in positional arguments so you gotta add `|undefined` there. Even the stuff it adds on top of JS is poorly thought out.
Ima help you out! Assuming your default satisfies the non-undefined type, you can just skip the union, it’s implied. This:
const foo = (bar: Bar = someBarSatisfyingValue) => {};
is identical to this: const foo = (bar: Bar | undefined = someBarSatisfyingValue) => {};
is identical to this: const foo = (bar?: Bar) => {
bar = bar ?? someBarSatisfyingValue;
};Re: TypeScript is now officially 10 years old
#165Earlier quoted context omitted.
Well the fact that it was available solely on Windows for so long was its doom. Actually I thought of using C# a few months ago, and I was like "Oh wait, does it even work on other platforms than Windows now?". Sure I'm not a C# developer, so I'm not up to date on C# news, but that's an issue if your goal is to drive adoption. Everyone that has heard of C# should know that it's now cross-platform.
Some things still seem to be Windows specific. If I want offline documentation (of the sort one can find at /usr/share/javadoc/java or /usr/share/doc/rust/html by installing the correct packages), every place I look tell me how to enable offline help in Visual Studio (for instance, https://learn.microsoft.com/en-us/teamblog/offline-book-refr... ). Someone here told me last time that there's a way to download whole se…
Other than that, and other than the obviously Windows-specific GUI and system management libraries, the rest of C#/.NET is pretty much fully multi-platform, maybe except a few obscure things.
Re: TypeScript is now officially 10 years old
#166Earlier quoted context omitted.
>You’re right on the first Strictly speaking, it takes exactly one such behavior (that you cannot even disable) for TS to stop being a superset of JS. >although classes are out of fashion, so this is low impact Looking at the TSC codebase, so are keyword arguments. The "in" thing is just to write very very long lines of multiple verbosely named positional arguments instead. That said, "clases are out of fashion" is a…
> I'm of the functional persuasion, yet I've found that classes are the ony way to write TypeScript that fits on your screen at all. Huh? I’m of the functional persuasion too, and I use classes in TS too, but for strategic reasons (well defined value objects are easier to reason about than duck typed POJOs, and they perform better too). But I’ve never found them more space-dense than the equivalent function-only code…
Sure, as long as I have to define them once and exactly once. Not always possible, as in the case of simple, garden-variety keyword arguments.
// foo is required, bar has default, baz is optional
type POJO = { foo: number, bar: number, baz?: number }
function myFn ({ foo, bar = 3, baz }: POJO = {}) {
// oh wait...
function myFn ({ foo, bar, baz }: POJO = { bar: 3 }) {
// oh wait...
function myFn ({ foo, bar, baz }: Partial = {}) {
bar ??= 3
if (foo === undefined) throw new Error("type safety")
// ...oh.
// maybe?:
function myFn ( foo, bar, baz }: POJO = { foo: undefined as never, bar: 3 }) {
// try :D
Technically the destructuring and the type declaration are completely separate things ofc (that just happen to look about the same because they're isomorphic but that's a watchlist word).But... it doesn't even try to infer the type of an untyped destructuring - even if it's a local function used only once!
>well defined value objects are easier to reason about than duck typed POJOs, and they perform better too
Long live those!
class BaseValueObject {
constructor (values: Partial // oh wait...
> Assuming your default satisfies the non-undefined type, you can just skip the union, it’s implied type Foo = { defaultBar?: Bar }
function main (foo: Foo, bar?: Bar = foo.defaultBar) {
// oh wait... parameter can't have question mark an initializer
function main (foo: Foo, bar?: Bar|undefined = foo.defaultBar) {
// this works but is silly and scaryish
>The only difference is that TS provides a fully optional shorthand for assigning both the type and value in constructor arguments. The actual behavior isn’t any differentThat's what a sane person would assume, no? Well, allow me to disappoint you (like that ever needs permission):
$ node
> Object.getOwnPropertyNames(new class Foo { a })
[ 'a' ]
$ npx ts-node
> Object.getOwnPropertyNames(new class Foo { a: any })
[]
Probably because it compiles them to a pre-standard, ES5-compatible class implementation based on good ol' `Foo.prototype`. And since they've already handled them one way, they can't become spec-compliant without breaking backwards compatibility.The other place where this shines through particularly egregiously is the support of ESM static import/export. Everybody's build tools been compiling that back down to CJS so hard that Node.js 16+ introduced intentional incompatibilities between CJS and ESM modes just to get people to finally switch to the standards-compliant module system. So you end up in a situation where the library is written in TypeScript with ESM syntax but the only available browser build is a CJS blob which completely defeats the main touted benefit of static imports/exports, namely dead code elimination...
So you decide what the hell, let's switch TSC to ESM and moduleResolution node16, and end up having to use something like https://github.com/antongolub/tsc-esm-fix because the only allowed fix for TSC doing the wrong thing is at the completely wrong level - https://www.typescriptlang.org/docs/handbook/esm-node.html - if you don't see what's wrong with that, you're one of today's lucky 10000...
Re: TypeScript is now officially 10 years old
#167Earlier quoted context omitted.
>There is no way to export a Go struct for consumption via FFI, for instance. I hope not. >Using TS, you can import any valid JS module without any special preparation Why does the DTS ecosystem exist then ( https://www.npmjs.com/package/@types/node etc)
d.ts files allow you to add types to imported JS. You’re free to import raw JS as an any type and the compiler won’t complain.
Re: TypeScript is now officially 10 years old
#168Earlier quoted context omitted.
> There's even the future possibility of much of its type syntax being absorbed back into JavaScript: https://github.com/tc39/proposal-type-annotations ... as comments. Which superficially resemble the syntax of type hints but do nothing. Which has to be one of the worst language design decisions of all time.
...as optional hints that don't require you to buy into a whole new toolchain.
I know a lot of people like it but it just seems like an ugly hack to me, extra syntax for the sake of an abritrary third party tool. I know I'm a dinosaur. I want to go back to the days of JQuery modules and FTP. Feh.
Re: TypeScript is now officially 10 years old
#169Earlier quoted context omitted.
>There is no way to export a Go struct for consumption via FFI, for instance. I hope not. >Using TS, you can import any valid JS module without any special preparation Why does the DTS ecosystem exist then ( https://www.npmjs.com/package/@types/node etc)
d.ts files allow you to add types to imported JS. You’re free to import raw JS as an any type and the compiler won’t complain.
$ echo "export class Foo { a = 1 }" > test.mjs
$ npx ts-node
> import('./test.mjs').then(console.log)
error TS7016: Could not find a declaration file for module './test.mjs'. '/home/user/Lab/test.mjs' implicitly has an 'any' type.
$ npx ts-node -O '{"allowJs":true}'
> import('./test.mjs').then(console.log)
Promise { }
Error [ERR_REQUIRE_ESM]: require() of ES Module /home/user/Lab/test.mjs not supported.
$ echo "module.exports.Foo = class Foo { a = 1 }" > test.cjs
$ npx ts-node -O '{"allowJs":true}'
> const { Foo } = require('./test.cjs')
> Foo
[class Foo]
> new Foo
Foo { a = 1 }
> function bar (foo: Foo) {}
TS2749: 'Foo' refers to a value, but is being used as a type here. Did you mean 'typeof Foo'?
No I did not, TypeScript, and that's about as much as it seems to interoperate. I guess in some cases practical migration might be viable - but as for the general case, the out-of-the-box experience seems to speak otherwise.It's not even viable to write in JS and manually write a DTS - no way to check em against each other. Except idk library in JS, test suite in TS anyway. So not a lot of lateral movement possible in practice.
Re: TypeScript is now officially 10 years old
#170Earlier quoted context omitted.
d.ts files allow you to add types to imported JS. You’re free to import raw JS as an any type and the compiler won’t complain.
Okay... $ echo "export class Foo { a = 1 }" > test.mjs $ npx ts-node > import('./test.mjs').then(console.log) error TS7016: Could not find a declaration file for module './test.mjs'. '/home/user/Lab/test.mjs' implicitly has an 'any' type. $ npx ts-node -O '{"allowJs":true}' > import('./test.mjs').then(console.log) Promise { } Error [ERR_REQUIRE_ESM]: require() of ES Module /home/user/Lab/test.mjs not supported. $ ech…
Try this:
// tsconfig.json
{
"compilerOptions": {
"outDir": "dist",
"module": "es2020",
"allowJs": true
},
"files": ["index.ts"]
}
// index.ts
import('./test.mjs').then(console.log)
> npx tsc && node ./dist/index.js
[Module: null prototype] { Foo: [Function: Foo] }