Open kaleidawave opened 1 year ago
Yay, Ezno - an actual alternative implementation of TS checking!
Glad to have you on here.
FWIW, a piece of feedback on part your list:
import type is a hint for bundlers (right?). If this was an engine, would it meant that the import doesn't import anything? Bit confusing so might be better to not include?
My experience with this: I'm building on top of some TypeScript libraries where the authors have used import
indiscriminately, for types and values.
Apparently, everyone else ever who has ever used those libraries was doing it through a bundler, which papers over the issue (and then some). But as I tried to compile them with tsc
to ESM (to use them with import maps - lovely instant feedback!), the type identifiers still ended up in the import
s alongside the value identifiers, while the exported types were obviously stripped. As a result, the libraries promptly broke at runtime, due to trying to import things that weren't there.
Since those libs were not tiny things, but hundreds of files, my only option was to write an AST codemod utility (using recast
), which parsed all the source files, took account of all exports (and reexports), determined what's a type and what's a value, and split each import
line into separate import
and import type
lines.
So that's one failure mode to take into account. Not importing anything would've been fine, but not discriminating between value and type imports ended up trying to import types at runtime.
Import assertions might make good "canonical" alternative to import type
.
The ones that are of slight concern are the modifiers under TypeOperatorType. I wonder whether these could be just done as generics e.g. readonly T could be ReadOnly
?
Agree about doing these as generics by default. Still, it's nice how TS allows these as prefixes to constructor arguments, and declares/assigns them automatically. Maybe out of scope for type checking, though.
import type
is a hint for bundlers (right?). If this was an engine, would it meant that the import doesn't import anything? Bit confusing so might be better to not include?
I was thinking about it as I wrote https://github.com/tc39/proposal-type-annotations/issues/176#issuecomment-1732690996
Let's say the first step is not adding new syntax, similar to how EcmaScript 5.1 just added tools before EcmaScript 6 came along and built on top of it.
In that other comment, I tried to see if we can leverage an existing syntax like
import ts4 from './local/interface/definitions/file.v4.d.ts' assert { checker: ['TypeScript','4','d.ts'] };
import flw from './local/interface/definitions/file.fjs' assert { checker: ['Flow','0.217.0'] };
but then got into thinking... what would those ts4
and flw
be?
TypeChecker
type?TypeChecker
can be a global object/namespace for utilities, and like Object.create
it can have TypeChecker.assert( s, ts4.SomeType )
or TypeChecker.as( s, 'flw.SomeType' )
or similar uses?flw.check( someIdentifier, 'flw.SomeType')
?In that other comment I mentioned someone might use out-of-band workers to provide load and run time checks, but an object returned via the imports with assertions or a global object that would provide a plug-in mechanism for any type checker for you to bring is also feasable I suppose, or hope so, through something like TypeChecker.register()
utility.
I mean that as much in favor of
not going to be one-to-one with the whole of TypeScript's syntax
as I'm trying to envision extensibility beyond TypeScript and Flow as to not have
in the future converge towards standards rather than diverging.
at least not standardize type syntax into EcmaScript, but standardize extensibility.
And it could be extensible enough that someone might
SQL
syntax for their domain objects,Yes, the above sounds like annotations. Overlap? Complement?
Sorry to interrupt, I'm not an expert but maybe we can simply add way to rigister any typechecker or transpiler like it implemented in node js (or simular) i mean --loader (transpiler loader). And just write js code with types, then in the beginning of "main" module import this checker or transpiler and it will typecheck and transpile code on the fly. It's not resolve typing "forks" problem but it may be can solve transpile stage problem may be it's enough for the first step. Sorry if this isn't the topic.
@niyarlatotep - you're welcome to open a new issue on that topic. I know some TC39 delegates shared some similar concerns, with the idea of "do we really need this, or would it be better to just provide options for different environments to be able to run TypeScript and other type checkers directly?". I saw this concern brought up in their meeting notes, but haven't really seen it get discussed in the github issues yet.
As I am building a checker for JS, I thought it would be a good to chime in with my point of view on some syntax things.
Firstly I think it would be great to standardise type syntax as a standard. Parsers and other tools are in the wild-west about how to handle type syntax. The most used type syntax extension don't have a good specification and process for adding syntax, leading some tools to be in the dark with trying to supporting codebases using it.
Things that I think would benefit from type annotations being in the source
"types"
field inpackage.json
etcThings that I think are important to upheld/accept in this proposal
x as Type
should be handled by Flow) and hopefully in the future converge towards standards rather than diverging.So while I would like to see an improvement on this front I have some concerns and questions with how this implemented
Reading the current document (as of 25/09/23), I think the concept of defined type annotations is a better that the original idea of tokens/comments. I would back that decision up with:
let x: &4a?asdd££ = 2
should be valid 😂my-parser
written in languagex
. And I want to treat the tokens in the way of type checkery
. That would require me to find a library compatible with the waymy-parser
represents tokens fory
. Ifmy-parser
had parsed it ahead of time, I could do things right away, wouldn't have to worry about eight tools parsing the token stream each and requiring caching for thatIMO 90% of the type annotations from TypeScript are perfect. Those being
4
,"my string"
)Console
)The ones that are of slight concern are the modifiers under
TypeOperatorType
. I wonder whether these could be just done as generics e.g.readonly T
could beReadOnly<T>
?Interface declarations and type aliases are pretty much fine. Not sure about
IndexSignature
though (if that is what I think it is).I don't think there is any way an experimental checker could benefit from having different syntax here. I don't think a more minimal and fixed set holds checkers back
So 👍 for type annotations (in function parameters, return and variables) and the two types of declarations.
The slight concern is for other places where type syntax can crop up (in TypeScript and others). Removing these would make this proposal simpler and adhere to non-bias. Some of these have too high of precedence and leak types outside of where they are usually found in declarations and variables. If they were included I think it would be difficult to document on things like MDN without favouring a implementation of checking or being difficult to explain.
Here is an inconclusive list of things I don't think should be included:
import type
is a hint for bundlers (right?). If this was an engine, would it meant that the import doesn't import anything? Bit confusing so might be better to not include?!
(non null assertion). IMO this signifies a failure in the checker knowledge. Should optional chaining and handing it at runtime be preferred? This also is quite a niche piece of syntax which instead could be used in the future for a lot of bigger features. For example Rust uses them to denote macros.as type
. If this were to be syntax, would it condone unsafe type casting? Are there are uses foras
syntax? Couldcast<T>
be used instead by checkers?as const
. Does it look likeconst
is type? Does this double up withObject.frozen
? Maybe in the future aObject.deepFreeze
could be considered instead of this syntax?satisfies
(in expressions). Do all checkers benefit from this? What should it be documented as?asserts *condition*
in the place of a function return#
?abstract
unclear of runtime implicationsMight have missed some others here. But those I think are cases that shouldn't be included in this specification. I think simplifying would the make this more acceptable to pass.
That is recommendations for syntax. I may open another issue later about reflection, runtime checking and direction later.