Skip to content

Instantly share code, notes, and snippets.

@HerbCaudill
Last active June 10, 2024 16:00
Show Gist options
  • Save HerbCaudill/0f45089098aa493fa944fe756957deb0 to your computer and use it in GitHub Desktop.
Save HerbCaudill/0f45089098aa493fa944fe756957deb0 to your computer and use it in GitHub Desktop.
effect/schema walkthrough
md hello-effect-schema
cd hello-effect-schema
pnpm init
pnpm i typescript @effect/schema effect fast-check vitest

Make tsconfig.json:

// tsconfig.json
{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "exactOptionalPropertyTypes": true
  },
  "include": ["**/*.ts"]
}

Make index.test.ts:

// index.test.ts
import { test, expect, expectTypeOf } from 'vitest'
import { Schema as S } from '@effect/schema'

Your first Struct

This is a schema with two properties: name is a string, and age is a number that comes in as a string.

const Person = S.Struct({
  name: S.String,
  age: S.NumberFromString,
})

Note that Person kind of looks like a TypeScript type, but it's not - it's a JavaScript object. We can obtain the corresponding type though:

type Person = typeof Person.Type
// equivalent to
// {
//   name: string
//   age: number
// }

const p = {
  name: 'alice',
  age: 42,
} satisfies Person

Note

It might seem strange to give the type the same name as the schema object, but it's idiomatic.

Encoding and decoding

One of the things a schema does is convert between some incoming form, to the form we want to work with.

In this example, we said age is a number that "comes in" as a string: Maybe it's persisted that way, or maybe we get it that way from an HTML input, or from an API call. In this case the encoded form is a string, and the decoded form is a number.

test('decodes Person', () => {
  const decode = S.decodeSync(Person)
  const encoded = {
    name: 'Alice',
    age: '25', // <- string
  }
  const decoded = decode(encoded)

  expect(decoded).toEqual({
    name: 'Alice',
    age: 25, // <- number
  })

  expectTypeOf(decoded).toMatchTypeOf<Person>()
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment