microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.94k stars 12.47k forks source link

Pure function validators #38346

Closed junaid1460 closed 4 years ago

junaid1460 commented 4 years ago

Search Terms

Custom type validators, pure function validators

Suggestion

having a defined way to document shape / value of a generic type like string , number. This could be a static compile time feature or it can be dragged into runtime.

Use Cases

Avoiding mistakes while creating cache keys Validators for URLs in form of string Validators for range

Examples


function url(urlStr: string) {
   // Test ur, if okay do nothing, else return error with examples
}

function ipAddress(ipString: string) {
   // Test ur, if okay do nothing, else return error with examples
}

const endPoint: string & ( url | ipAddress ) = "0.0.0.0"

Checklist

My suggestion meets these guidelines:

MartinJohns commented 4 years ago

I'd say this is a duplicate of #202 (combined with type guards). The cases "url" and "ip address" could also be solved by #6579.

junaid1460 commented 4 years ago

yes, but regex makes it harder to read, also this looks more generic can be applied to any type, regex could be kind of validator within

I mean


const port: number & range(8000, 9000) = 8001

where range could give a curried function that can accept type 'number' which is 8001

junaid1460 commented 4 years ago

This could be just compiler internal implementation for most of the use cases

awerlogus commented 4 years ago

If we'll drag it into runtime, it will give us ability to create programs with undefined behavior

For example:

const lessThanHalf = (num: number) => num < 0.5

const a: number & (lessThanHalf) = Math.random()

But if we'll check it statically, it will not be possible even to compile this code because the type number, returned by the random function, will be not assignable to the type number & (lessThanHalf).

So, we can just add predicate to the type of value after checking the value with it.

const lessThanHalf = (num: number) => num < 0.5

const num = Math.random()

if(lessThanHalf(num)) {
// num is `number & (lessThanHalf)` here
} else {
// num is `number` here
}

But I still have a lot of questions: 1) How about functions with different names, but which are doing the same?

const a = (num: number) => true
const b = (num: number) => true

const c = 0

if(a(c)) {
  // Should this be valid?
  const d: number & (b) = c
}

2) Should predicates be pure? Why?

3) Can we use only named functions or anonymous too?

If yes, how should the type of variable b look like?

const a = 0

if(((num: number) => true)(a)) {
  // What is the type of b?
  const b = a
}

If no — don't you think that limiting the checks with named functions only will unnecessarily increase the size of the code?

4) What about generic predicates?

5) How to handle this case?

function a() {
  const b = (n: number) => true

  return (n: number & (b)) => n
}

const c = a()

The type of c refers the scope that is not accessible from the scope where c is declared


IMHO: the approach proposed in this issue adds much more problems than it solves

junaid1460 commented 4 years ago
junaid1460 commented 4 years ago
junaid1460 commented 4 years ago

And mainly the validator api should have a design strategy where we decide what's the signature of predicate should be, It should never be any function. Every api needs to have schema and should be predictable.

junaid1460 commented 4 years ago

Everything that has schema should be statically assertable, We define conventions in our codebase that's documented in a cornered file example :

RyanCavanaugh commented 4 years ago

I can't tell from this proposal whether you're proposing that TypeScript evaluate ipAddress at compile time (which we're not going to do), or if you're proposing that TypeScript insert code into the JS emit to cause ipAddress to be evaluated at runtime, which we also wouldn't do.

junaid1460 commented 4 years ago

I am proposing that literals can be evaluated at compile time @RyanCavanaugh . Node mostly runs on api side and does lots of query/scripts which can be statically evaluated.