never conditional type undefined
With an interface like this:
interface A<T> {
n: T extends number ? number : never
s: T extends string ? string : never
}
this doesn't compile:
const a: A<string> = {
s: "blah"
}
The type checker still requires the n field, even though it should be never. In other words, as it stands, you can't create an object of this type (as far as I know). My suggestion is to take care of this case and allow this construct.
I thought this worked in some earlier (not too recent) version of TypeScript. I remember that even VS code knew that it shouldn't suggest n in this example. It now does suggest the option. In actual code where we previously used something like this, the fields are optional, which is still working. In the above case, I need the field to be required.
Since I'm apparently not sure if it's a regression or intended behaviour, I'm posting this as a feature request.
We would use this feature for objects like the above where some fields are required only if some type parameter has some type. That would in our case usually be objects of a more declarative nature, such as configs or options objects (in case a function would otherwise have too many arguments).
The above case is solvable, as suggested on the TS site (code copied from there):
type BoxedValue<T> = { value: T };
type BoxedArray<T> = { array: T[] };
type Boxed<T> = T extends any[] ? BoxedArray<T[number]> : BoxedValue<T>;
but for a larger number of fields and/or type parameters, this explodes and leads to more and more code duplication.
Another solution would be to create multiple interfaces and let them extend each other. That feels more like the Java way of doing things.
Maybe Pick offers another way out, but that would still require additional boiler plate which in my opinion shouldn't be necessary.
This is part of our project that currently doesn't work:
export interface ModuleConfig<T, M extends Mutability> {
readonly path: Path
readonly dataSource?: DataSource<T>
readonly rules: M extends Mutability.ENABLED ? ObjectRules<T> : never
}
The rules field is always required at the moment.
My suggestion meets these guidelines:
Some might use the never type in a prop as signaling that the entire type cannot be constructed. And, in general, that's what never means.
In particular, I would be pretty upset because you'd break my CompileError<> type =P
https://github.com/microsoft/TypeScript/issues/23689#issuecomment-512114782
You might be interested in this, https://github.com/microsoft/TypeScript/issues/13195
You can easily apply this to your own types already if you want to:
As @AnyhowStep mentioned, an object with a never property can't be constructed. @nmain 's suggestion would be the correct way to approach this -- you could also use a different signaling type if you wanted.
Thanks for your suggestion @nmain, I'll give that a try.
Most helpful comment
You can easily apply this to your own types already if you want to:
Playground