Hacker News new | ask | show | jobs
by kazoomonger 1940 days ago
What would happen if I wanted only some fields to be required? To borrow from the GP example, something like this:

    struct Person<F> {
        pub name: F<String>,
        pub age: Option<u32>,
    }
With `Person<Box>` still leaving `age` as optional.
4 comments

You can do it like this:

  type RequiredKeys<O, K extends keyof O> = Omit<O, K> & Required<Pick<O, K>>
  type Person = {
    name?: string
    age?: number
  }
  type RequiredName = RequiredKeys<Person, 'name'>
The opposite (making some of the fields optional, without affecting the rest) would be written like this:

  type OptionalKeys<O, K extends keyof O> = Omit<O, K> & Partial<Pick<O, K>>
Yes, you can do this in typescript, but you can also lie about it in typescript. To do it provably, you would construct a function that accepted the more generic version and then, using type assertions (ie the typescript compiler infers the type from declared runtime behavior), it would return a narrowed type.

If one caller passes our type narrower with {age:F<u32>} then the return value of the function will be narrowed to that type, but a broader criteria can still be specified for the generic instance.

Add an extra generic parameter.

(Also, it shouldn't be Box; you'd want a bog-standard generic newtype for this, not an extra heap allocation.)

yeah, I picked Box mostly as a pedagogical instance of the identity functor that already exists in the stdlib - in the real world you'd definitely want `struct Identity<F>(F)` instead.
Yeah there's going to be tradeoffs either way, the question is how often they come up in the situations the language is designed to target (versus random examples designed to showcase some obscure corner of PLT)... In this case for TS you might craft your own mappings that work like AllButXOptional<Person, 'age'>, or similar. So it's controlled externally versus internally, which who knows if thats better or not. One benefit of the TS approach is that it's a bit more composable... you can imagine things like OptionalIfRequiredInOther<ComplexPerson, SimplePerson>.