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

Thoughts on the future direction for pdsl #99

Open
ryardley opened this issue Nov 29, 2019 · 0 comments
Open

Thoughts on the future direction for pdsl #99

ryardley opened this issue Nov 29, 2019 · 0 comments

Comments

@ryardley
Copy link
Owner

ryardley commented Nov 29, 2019

The following are some draft thoughts and do not indicate a well thought through position feel free to think about it but please reserve comments until draft status is removed.

PDSL thoughts on direction

So I have been thinking about this lib and how it can progress in the future and have come up with a few observations I think need to be addressed before it will become super relevant and compete with existing schema driven validation alternatives such as yup or joi:

Is the exact matching syntax hampering pattern matching usecase?

Exact matching syntax has added some really beneficial things especially around the way we can validate fixed length arrays with mixed values.

Typed arrays has meant we have a concise syntax for dealing with arrays that have a defined item type.

It is common in the wild to be able to express arrays as containing a fixed type say having an array of strings or an array of Person objects. It is less common to need to check for a specific item at an index being a specific type however it is a great feature to be able to do this especially when checking tuples and I think the current syntax around array matching that has come from the exact matching syntax PR is excellent.

However one of the main purposes of pdsl is to act as a shorthand pattern matcher or filter of sorts which means things such as checking if an object has a shape we can use. The key word is 'shorthand'. We almost always want to take something unknown and consolidate it towards a known thing that we can use. In the same way that interfaces allow This means that 90% of the time we only care we can use the object for a certain purpose and we don't care about any extra cruft on that object. Basically it is super annoying to have to add ... all the time because it is very easy to forget. One example where this is often the case would be checking a GraphQL result shape. Most of the time we don't want to care about stray __typename fields for example.

I think a solution here is to provide a set of configuration options that allows an exact matching in objects mode and a mode without exact matching in objects. We then need a way to get around it for each mode too:

import pdsl from 'pdsl';

// loose matching in objects
p.create({strictObjects:false})`{
  name: string,
}`({
  __typename: 'Person',
  name: 'Richard',
}); // true

// Escape hatch to provide strict matching on specific object
p.create({strictObjects:false})`{|
  name: string,
|}`({
  __typename: 'Person',
  name: 'Richard',
}); // false

// strict matching in objects
p.create({
  strictObjects: true
})`{
  name: string
}`({
  __typename: 'Person',
  name: 'Richard'
}); // false

// escape hatch
px`{
  name: string,
  ...
}`({
  __typename: 'Person',
  name: 'Richard'
}); // true

Usage with type-focussing

Secondly TypeScript is becoming more and more important when it comes to JavaScript and being able to synchronise PDSL expressions with TypeScript will make things much easier for developers. There is already a large overlap however there are times where working with typescript is annoying. This is especially true with the situation of working with data fetching layer type generation. Often types will be generated from Schemas and if you follow best practices often you get nullish or incomplete types and the frontend is expected to check the objects for those values to ensure our data is workable.

It may make sense to be able to generate types to a file from all your p expressions in a similar way to the way gql-gen works.

// generated/pdsl.ts
export interface RegisteredUser {
  role: "admin" | "manager" | "editor";
  name: string;
  isCompleteRegistration: true;
}
// generated/graphql.ts
export type GeneratedQueryUser = {
  __typename?: string | null 
  role?: "admin" | "manager" | "editor" | null;
  name?: string | null;
  isCompleteRegistration?: true | null;
}
import {GeneratedQueryUser} from './generated/graphql.ts';

// It might be possible to automatically infer types by using an alias key
// This would mean that the following would automatically be a guard for 
// the RegisteredUser interface. I would have preferred to be able to check 
// against the template string itself but this appears not to be possible with 
// `TemplateStringsArray`
const isRegisteredUser = p.as('RegisteredUser')`
   role: "admin" | "manager" | "editor",
   name: string,
   isCompleteRegistration: true
`;

export function getRegisteredUserList(users:GeneratedQueryUser[]):RegisteredUser[] {
  return users.filter(isRegisteredUser);
}

Does optional chaining make this library obsolete?

Part of what is helpful with this lib is the fact that it makes javascript more concise.

New additions like optional chaining to javascript has helped this out greatly which I think is absolutely fantastic:

const isValidStr = a => typeof a?.thing?.value === 'string' && 
  a?.thing?.value?.length > 3

vs

const isValidStr = a => a.thing && a.thing.value && typeof a.thing.value === 'string' && 
  a.thing.value.length > 3

However it is still shorter and more illustrative to express the validation in PDSL especially with the new length syntax:

const isValidStr = p`{ 
  thing: { 
    value: string[3] 
  } 
}`;

I also think this is cleaner than yup:

const isValidStr = yup.object().shape({
  thing: yup.object().shape({
    value: yup.string().required().min(3)
  })
}).isValidSync

I think realistically whilst this means that there is less of a chance someone would reach for this lib to do simple validation of objects with a couple of properties. When values and structures become more complex PDSL shines.

How can this make sense in the context of form validation say with a lib like formik?

  • Can we derive TypeScript types directly from the schema?
  • How can this be integrated in server side validation say in the context of a graphql schema?
@ryardley ryardley changed the title Draft: Thoughts on the future direction for pdsl 🚧 Draft: Thoughts on the future direction for pdsl Nov 29, 2019
@ryardley ryardley changed the title 🚧 Draft: Thoughts on the future direction for pdsl 🚧 Draft (please ignore): Thoughts on the future direction for pdsl Nov 29, 2019
@ryardley ryardley changed the title 🚧 Draft (please ignore): Thoughts on the future direction for pdsl 🚧 (this is draft): Thoughts on the future direction for pdsl Nov 29, 2019
@ryardley ryardley changed the title 🚧 (this is draft): Thoughts on the future direction for pdsl 🚧 (under construction): Thoughts on the future direction for pdsl Dec 2, 2019
@ryardley ryardley changed the title 🚧 (under construction): Thoughts on the future direction for pdsl Thoughts on the future direction for pdsl Mar 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant