Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine isReadonlyOf and related #60

Closed
lambdalisue opened this issue Feb 13, 2024 · 4 comments
Closed

Refine isReadonlyOf and related #60

lambdalisue opened this issue Feb 13, 2024 · 4 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@lambdalisue
Copy link
Member

TypeScript offers the Readonly<T> type function and the readonly keyword. However, the isReadonlyOf function seems a bit ambiguous. I propose the following improvements:

  • Enhance isReadonlyOf for Array, Tuple, and Object types.
  • Introduce isReadonlyFieldOf for checking/annotating the readonly status of object fields.
  • Rename isOptionalOf to isOptionalFieldOf to maintain consistency with isReadonlyFieldOf. This change aligns with the handling of ? for object fields.
@lambdalisue lambdalisue added the enhancement New feature or request label Feb 13, 2024
@lambdalisue lambdalisue added this to the v4 milestone Mar 4, 2024
@lambdalisue
Copy link
Member Author

Several pattern to annotate fields as ? or readonly.

import { is, Predicate } from "./mod.ts";

function optional<K extends PropertyKey>(name: K): K {
  return name;
}

function readonly<K extends PropertyKey>(name: K): K {
  return name;
}

function annotate<T>(
  pred: Predicate<T>,
  annotations: { optional?: boolean; readonly?: boolean },
): Predicate<T> {
  return pred;
}

const as = {
  Optional: <T>(pred: Predicate<T>) => pred,
  Readonly: <T>(pred: Predicate<T>) => pred,
};

const pattern1 = is.ObjectOf({
  [optional("optionalField")]: is.String,
  [readonly("readonlyField")]: is.String,
  [readonly(optional("readonlyOptionalField"))]: is.String,
});

const pattern2 = is.ObjectOf({
  optionalField: annotate(is.String, { optional: true }),
  readonlyField: annotate(is.String, { readonly: true }),
  readonlyOptionalField: annotate(is.String, {
    optional: true,
    readonly: true,
  }),
});

const pattern3 = is.ObjectOf({
  optionalField: as.Optional(is.String),
  readonlyField: as.Readonly(is.String),
  readonlyOptionalField: as.Readonly(as.Optional(is.String)),
});

I personally like as.* pattern

@Milly
Copy link
Collaborator

Milly commented Apr 15, 2024

The optional annotation is also used as an element of isTupleOf and isParametersOf, so it is impossible to apply pattern 1 of annotating object keys.

@lambdalisue
Copy link
Member Author

lambdalisue commented Apr 15, 2024

What I'm thinking of it is

  • as.Optional - Optional for a field or an element
  • as.Readonly - Readonly for a field or an element
  • is.PartialOf - Optional for all fields or elements of object, array, tuple, etc.
  • is.ReadonlyOf - Readonly for all fields or elements of object, array, tuple, etc.
type A = {
  foo?: string;
  readonly bar: string;
  readonly hoge?: string;
};

// Predicate<A>
const a = is.ObjectOf({
  foo: as.Optional(is.String),
  bar: as.Readonly(is.String),
  hoge: as.Optional(as.Readonly(is.String)),
});

type B = Partial<A>;

// Predicate<B>
const b = is.PartialOf(a);

type C = Readonly<A>;

// Predicate<C>
const c = is.ReadonlyOf(a);

@lambdalisue lambdalisue self-assigned this Jul 31, 2024
@lambdalisue
Copy link
Member Author

#87

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants