Git Product home page Git Product logo

Comments (8)

gcanti avatar gcanti commented on May 17, 2024

Relevant gcanti/flow-io#19

from io-ts.

goodmind avatar goodmind commented on May 17, 2024

@niieani hey, it looks that microsoft/TypeScript#13940 is what you need. It allows writing AST transformations so you can replace interfaces/types with runtime representation like flow-runtime does

from io-ts.

gcanti avatar gcanti commented on May 17, 2024

@goodmind Interesting, thanks for the link

so you can replace interfaces/types with runtime representation

@niieani what's the main use case for this?

from io-ts.

niieani avatar niieani commented on May 17, 2024

@gcanti best use case currently is ensuring the points-of-contact of typed and untyped code are valid, i.e. the contracts that the types are, hold up in practice. Another one would be points-of-contact for deserializers, or when verifying that interfaces for external data (e.g. JSON from the server) are correct.

We currently use flow-runtime for the very same reasons in development (naturally this is off in production builds), but helps to find subtle bugs in both of these cases.

from io-ts.

gcanti avatar gcanti commented on May 17, 2024

@niieani Indeed IO validation is the main goal of io-ts, though validations must be defined "by hand"

import * as t from 'io-ts'
import { pathReporterFailure } from 'io-ts/reporters/default'

function validateEndpoint<T>(value: any, type: t.Type<T>): Promise<T> {
  if (process.env.NODE_ENV !== 'production') {
    return t.validate(value, type)
      .fold<Promise<T>>(
        errors => Promise.reject(pathReporterFailure(errors)),
        x => Promise.resolve(x)
      )
  }
  return Promise.resolve(value)
}

function validate<T>(value: any, type: t.Type<T>): T {
  if (process.env.NODE_ENV !== 'production') {
    return t.validate(value, type)
      .fold<T>(
        errors => { throw new Error(pathReporterFailure(errors).join('\n')) },
        x => x
      )
  }
  return value
}

const RTPerson = t.interface({
  name: t.string
})

// can be extracted from RTPerson
type Person = {
  name: string
}

function untrustedEndpoint(id: string): Promise<{ data: Person }> {
  return Promise.resolve({ data: {} })
}

function untrustedLibraryAPI(a: number, b: number): number {
  return a + 'wrong' as any // should be a sum
}

untrustedEndpoint('id')
  .then(res => validateEndpoint(res.data, RTPerson))
  .then(
    person => console.log(person),
    error => console.error(error) // => [ 'Invalid value undefined supplied to : { name: string }/name: string' ]
  )

validate(untrustedLibraryAPI(1, 2), t.number) // throws Invalid value "1wrong" supplied to : number

Now back to this issue (Transpile TS code to JS), what would you like to have or what do you do with flow-runtime in order to get the same behavior? I'd love to see some pratical example in order to understand correctly what you mean

from io-ts.

niieani avatar niieani commented on May 17, 2024

@gcanti I think this behavior is pretty much the ideal, given it supports all the TS-specific features: https://codemix.github.io/flow-runtime/#/try

from io-ts.

gcanti avatar gcanti commented on May 17, 2024

@niieani How do you use flow-runtime in order to validate API payloads? This doesn't raise any error

type Person = {
  name: string
}

function untrustedEndpoint(id: string): Promise<{ data: Person }> {
  return Promise.resolve(null) // <= wrong
}

untrustedEndpoint('id')

from io-ts.

niieani avatar niieani commented on May 17, 2024

@gcanti good catch, it's probably something flow-runtime should handle in the future. To tell the truth we still haven't had the time to migrate from babel-plugin-typecheck to flow-runtime, but we also don't expect it to work perfectly, since we only treat it as a debug/coding-helper tool -- to catch errors faster, not as the ultimate source of truth.

The place where the above problem would be caught would be once it is passed to another function, e.g.

type Person = {
  name: string
}

type Endpoint = { data: Person }

function untrustedEndpoint(id: string): Promise<Endpoint> {
  return Promise.resolve(null) // <= wrong
}

function processPersonNameFromEndpoint(response : Endpoint) {
  return response.data.name
}

untrustedEndpoint('id').then(processPersonNameFromEndpoint)

from io-ts.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.