4 ms·
In TS this would be flipped: type Person = { name: string; age: number; } type SomeFieldsMissing = Partial<Person>; type AllFieldsRe
by meetups323 6y ago
In TS this would be flipped:
type Person = {
name: string;
age: number;
}
type SomeFieldsMissing = Partial<Person>;
type AllFieldsRequired = Required<Person>; // No real change in this case
Where Partial and Required are defined like:
type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
type Required<T> = { [P in keyof T]-?: T[P]; }
What would you think of something like this ("mapped types")? They can get fairly powerful: https://www.typescriptlang.org/docs/handbook/2/mapped-types.html https://www.typescriptlang.org/docs/handbook/2/mapped-types....
- kazoomonger 6y agoWhat 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.
- wizzwizz4 6y agoAdd 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.)
- glittershark 6y agoyeah, 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.
- meetups323 6y agoYeah 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>.
- IggleSniggle 6y agoYes, 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.
- ksbrooksjr 6y agoYou 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>>
- glittershark 6y agothat seems like something that would only really work with a type system that's as structural as TS (vs rust, which is very nominal)
- a1369209993 6y agoThat superficially looks horrible. How do you write `Person (Compose Maybe Maybe)`, even, never mind anything more sophisticated? Edit, for that matter, how do you deal with a `Person f` that includes a `f (Maybe Something)` without confusing "the user didn't specify a `Maybe Something`" with "the user specified a `Maybe Something` with value `Nothing`" (or vice versa)?
- meetups323 6y agoI'm not sure what you mean by `Person (Compose Maybe Maybe)`? Is that a person with values you have to unwrap twice to use? That's not really a thing in TS, it either is undefined or isn't. But if you need to shoehorn Haskell into TS for whatever reason I guess you could do something like: type Maybe<T> = {hasValue: false} | {hasValue: true, value: T} type Shoehorn<T> = { [P in keyof T]-?: Maybe<Maybe<P>> }
- a1369209993 6y ago> I'm not sure what you mean by `Person (Compose Maybe Maybe)`? Is that a person with values you have to unwrap twice to use? `Compose Maybe Maybe T` (equivalently `Maybe (Maybe T))`), has N + 2 values (where N in the probably-infinite number of values T has): . N values consisting of a T . 2 different values that do not include a T It's also equivalent (via 1 + (1 + N) = (1 + 1) + N) to `Either Bool T`. And yes, `Person f` contains values of type `f Whatever`. > it either is undefined or isn't. Values are never undefined. They might be defined as a object that's called "undefined", but that is a specific, defined, value. And, apropos of the above, it's a single value, out of the two distinct non-T values being represented. Which is part of why the example at https://news.ycombinator.com/item?id=26277598 https://news.ycombinator.com/item?id=26277598 looks horrible - it seems like it would confuse the two different non-T values with each other if `Person f` includes a `f (Maybe T)`. Edit: actually, clarified the previous comment a bit, too.
- gavinray 6y agoI don't know what kind of software you write, but I build the same CRUD app and UI-flavor-of-the-month frontend, over and over. I have no clue what "N + 2 values (where N in the probably-infinite number of values T has): N values consisting of a T" means and I've done fairly well for myself. Why does anyone need this to write and deploy CRUD apps and put forms + buttons on stuff?