You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
test(config): remove strictNullChecks errors from compiler/config
This is another PR for removing _some_ strictNullChecks errors, in
particular in the code related to loading and validating the `Config`.
This PR proposes a change to how the `Config` loading / validation
pipeline works. Instead of dealing the whole way through with a single
`Config` type, this puts a boundary in place which is crossed in the
`validateConfig` function between an `UnvalidatedConfig` and a `Config`.
How does this work? Basically `Config` is the type that we expect to be
able to pass around everywhere else in the codebase without issue, while
`UnvalidatedConfig` is a type which is around to specifically denote the
fact that the object we're dealing with is sort of a 'config in
progress' and it cannot yet be used freely throughout the compiler.
`UnvalidatedConfig` is implemented w/ a new type I added called `Loose`,
which looks like this:
```ts
type Loose<T extends Object> = Record<string, any> & Partial<T>
```
`UnvalidatedConfig` looks like this:
```ts
type UnvalidatedConfig = Loose<Config>
```
This amounts to 1) making all properties on `Config` optional (via
`Partial`) and 2) allowing access to properties which are _not_ defined
on `Config`.
We need the former because this opens the door to later changing the
typing of properties on `Config` to _not_ all be optional (as they
currently are). This will be a big help towards turning
`strictNullChecks` on, since doing so right now results in a literal ton
of errors around property access on `Config` objects—consider, for
instance, that currently `Config.sys` is an optional property, so _every
time_ the `.sys` property is accessed we'll get an error with
`strictNullChecks`.
We need the latter change because with `strictNullChecks` if you do
something like the following you'll get a type error:
```ts
interface Foo {
bar: string
}
let obj: Foo = {
bar: "hey!"
}
let otherPropValue = obj["asdfasdf"]
```
TypeScript here will (and should!) throw an error for `otherPropValue`
because the index type on `Foo` is `"bar"` and not `string`. The
`Record<string, any> &` bit in the definition of `Loose` lets us access
properties not defined on `Config` in our validation code (for an
example of this see the `setBoolean` function in
`/src/compiler/config/config-utils.ts`) without giving up on types in
`Config` entirely. What do I mean by that? Basically just that if you do
this:
```ts
let config: UnvalidatedConfig = someFunctionThatProducesConfig();
```
then the type of `config["somePropertyWeDontDefine"]` will be `any`, and
we can do things we need to with such properties within the validation
code, _but_ if I access `config.sys` the type will still be
`CompilerSystem`. So for this reason I think typing something as
`Loose<T>` is superior to just doing `Record<string, any>` or `Object`
or (shudders) `any`.
This commit just gets us started with this sort of 'lifecycle' for
Config objects (they start out as `UnvalidatedConfig`s, get passed
through `validateConfig` and come out as full `Config` objects) and more
work will be needed to get all of the config validation and loading code
on board. Once we do that we can safely start removing optional
properties on `Config` itself, since we'll have assurance from the
compiler that anything marked `Config` has already been fully validated
and should always have, e.g., a `.sys` property, a `buildDir` property,
etc. This will make it much easier for us to turn `strictNullChecks` on
without having to sprinkle the codebase with (literally hundreds of)
optional property accesses (`?.`).
0 commit comments