Open kaljarv opened 1 month ago
A way to start is to look at the style guides of existing OS projects (with TS)
Undefined vs null
It seems that the convention in TypeScript is that undefined values have not been defined yet, whereas null values indicate intentional absence of a value. Therefore, I would not just change all undefineds to null, because they have different meanings.
Some sources say that the use of undefined is recommended and null is discouraged (all these cite the coding guidelines for contributors of typescript but this does not necessarily mean that projects made with typescript should only use undefined). Many seem to prefer using only undefined.
Some also argue, that you should not assign undefined to any value, because it is easier to debug programs if you know that if you get undefined it was because the variable never got set. Null indicates a variable that is empty or contains nothing (but has type etc)
https://www.reddit.com/r/typescript/comments/11dpu05/undefined_vs_null/
I could not really find any repos or style guides that take a stand on what should be used. Google and ts.dev styling guide both say that many js apis use undefined and many dom and google apis use null, so the appropriate value depends on the context.
See also TS Style Guide.
Enums vs string unions Why is it not good to use enums comparison
Why use string literals:
Why use Enums:
The style guide looks like something we could adopt, although these rules might need discussion:
<button {disabled}>
shorthand.We might need some automatic type generation for services and the like, e.g. Strapi types and translations. It'd be worthwhile to investigate how this can be best achieved.
Do we have lot of cases where we have to use interfaces?
I think I often use string[]
but I don't have a strong preference.
- https://mkosir.github.io/typescript-style-guide/#args-as-discriminated-union
- This seems to sometimes cause linter issues if used for component properties, but could be enforced for functions proper
What kind of linter issues?
- https://mkosir.github.io/typescript-style-guide/#naming-conventions
- The boolean naming convention could otherwise be followed, but we often want to use HTML attribute names for the matching properties to use the Svelte
<button {disabled}>
shorthand.
Agree, and in those cases it's pretty clear that those are boolean.
- https://mkosir.github.io/typescript-style-guide/#type-definition Do we have lot of cases where we have to use interfaces?
Not necessarily that many, and most all can be converted into types. Possible contexts where interfaces are needed are:
vaa-matching
and vaa-data
models where we want to only dictate the minimum requirements for the objects they accept, but maybe these could still be types…
- https://mkosir.github.io/typescript-style-guide/#array-types I think I often use
string[]
but I don't have a strong preference.
Me too :D, but I'm starting to think that Array<string>
might be preferable because it's easier to distinguish from string
. An added benefit is a less messy initialisation for empty typed arrays:
const foo = new Array<Bar>();
// vs.
const foo: Bar[] = [];
- https://mkosir.github.io/typescript-style-guide/#args-as-discriminated-union
- This seems to sometimes cause linter issues if used for component properties, but could be enforced for functions proper What kind of linter issues?
I had such a discriminated construction for the ButtonProps
type in $lib/compontents/icon
, which only allowed for some values of iconPos
for some variant
s. It was easy enough to describe in the interface, but then on some pages where the component is used with variables as the values for these properties, the linter would rightly complain it couldn't be sure the combination was correct. In theory, this could be worked around but that seemed a bit complicated, but it would ensure correct usage on the other hand 🤔 . E.g.
let foo: ButtonProps['variant'];
let bar: ButtonProps['iconPos'];
// Set values here
// This will still be bad, because we don't know if `foo` and `bar` are compatible
<Button variant={foo} iconPos={bar}/>
// Could be possibly worked around this way or so
let props: Partial<ButtonProps> = foobar
? { variant: 'iconAnywhere', iconPos: 'left' }
: { variant: 'iconOnlyRight', iconPos: 'right' };
<Button {...props}/>
<Button>
, but if it gets too fraught, we can make exceptions for components<button {disabled}>
shorthand.
Harmonize code formatting globally:
@default
statements from@component
docstrings because they break the IDE layoutundefined
s tonull
s if this is the recommended approach. At least,null
is compatible with JSON, which is a plus.null
andundefined
, which ought to be checked as well.MISSING_ANSWER
is now defined asundefined
(pun not intended) invaa-matching
, butnull
might be a better option because of JSON compatibility.setTimeout
is used to wait for DOM updates and see if those can be converted to usetick
.eventDispatcher
.