effect-tsでSchema

Schemaの型や値の制限のメモ

# シンプルな型の場合

シンプルな型では値制限や型制限ができる


## 値制限

値の範囲を指定できる、型はnumberなどのシンプルなもの

参考 

https://effect.website/docs/schema/default-constructors/

下記の２つの変数は特に違いがない
リンクにあるように制限外の値が入力されるとエラーが発生する

```ts
import { Schema } from 'effect'
import { describe, it } from 'vitest'

describe('Schema make シンプルな型', () => {
  it('値制限', () => {
    const schema = Schema.NumberFromString.pipe(Schema.between(1, 10))
    type typeSchema = Schema.Schema.Type<typeof schema>

    const number5 = schema.make(5)
    console.log(number5)

    const number5_: typeSchema = 5
    console.log(number5_)
  })
})
```


## 型制限

stringなどのシンプルな型でのnewの方法の制限する

参考

https://effect.website/docs/schema/advanced-usage/#reusing-an-existing-branded-constructor

userid_3 は 静的解析エラーが出るが、実行時エラーは出ないため
anyなどを利用すれば無視できるが、それをしなければbuild時に気づくことができる

```ts
import { Brand, Schema } from 'effect'
import { describe, it } from 'vitest'

describe('Schema make シンプルな型', () => {
  it('型制限', () => {
    type typeUserId = string & Brand.Brand<'UserId'>
    const UserId = Brand.nominal<typeUserId>()
    const UserIdSchema = Schema.String.pipe(Schema.fromBrand(UserId))

    const userid = UserIdSchema.make('test')
    console.log(userid)

    const userid_2: typeUserId = UserIdSchema.make('test')
    console.log(userid_2)

    const userid_3: typeUserId = 'test'
    console.log(userid_3)
  })
  it('型制限', () => {
    const UserId = Schema.String.pipe(Schema.brand('UserId'))
    type typeUserId = Schema.Schema.Type<typeof UserId>

    const userid = UserId.make('test')
    console.log(userid)

    const userid_2: typeUserId = UserId.make('test')
    console.log(userid_2)

    const userid_3: typeUserId = 'test'
    console.log(userid_3)
  })
})
```

# 複雑な型の場合

複雑な型にあるkeyの型などはシンプルな型と同じようなことができる、
それに加えて複雑な型では以下のようなことができる

## デフォルト値 (＋必須ではない)

デフォルトの値を使用でき、明示的に使用しないため、後で変更もしやすそう

参考

https://effect.website/docs/schema/advanced-usage/#basic-default

```ts
import { Schema } from 'effect'
import { describe, it } from 'vitest'

describe('Schema make struct', () => {
  it('デフォルト値', () => {
    const Product = Schema.Struct({
      quantity: Schema.optionalWith(Schema.NumberFromString, {
        default: () => 1
      })
    })

    // 1
    console.log(Schema.decodeSync(Product)({}))
    console.log(Schema.decodeSync(Product)({ quantity: undefined }))
    console.log(Product.make({}))

    // 2
    console.log(Schema.decodeSync(Product)({ quantity: '2' }))
    console.log(Product.make({ quantity: 2 }))
  })
})
```



## 必須

値を設定していない場合にエラーを出すことができる
静的解析時も実行時も両方エラーになる

ただし、変な値も含んだ型の代入が可能

```ts
import { Schema } from 'effect'
import { describe, it } from 'vitest'

describe('Schema make struct', () => {
  it('必須', () => {
    const Product = Schema.Struct({
      quantity: Schema.NumberFromString
    })
    type typeProduct = Schema.Schema.Type<typeof Product>

    // エラーあり
    console.log(Schema.decodeSync(Product)({}))
    console.log(Schema.decodeSync(Product)({ quantity: undefined }))
    console.log(Product.make({}))

    // エラーなし
    console.log(Schema.decodeSync(Product)({ quantity: '2' }))
    console.log(Product.make({ quantity: 2 }))

    const p: typeProduct = Product.make({ quantity: 2 })
    const p2 = {
      quantity: 2,
      a: 123
    }
    const p3: typeProduct = p2
  })
})
```


## 型制限

シンプルな型の時と同じような型制限が利用できる
ただし、型の代入時は静的解析エラーは出るが実行時エラーはでない

```ts
import { Schema } from 'effect'
import { describe, it } from 'vitest'

describe('Schema make struct', () => {
  it('型制限', () => {
    const Product = Schema.Struct({
      userid: Schema.String.pipe(Schema.brand('UserId'))
    })
    type typeProduct = Schema.Schema.Type<typeof Product>

    console.log(Schema.decodeSync(Product)({ userid: '2' }))
    console.log(Product.make({ userid: Product.fields.userid.make('2') }))

    const p: typeProduct = Product.make({ userid: Product.fields.userid.make('2') })
    const p2 = {
      quantity: 2,
      a: 123
    }
    const p3: typeProduct = p2
    const p4: typeProduct = p
  })
})
```

## Schemaを使用しない場合

デフォルト値や値の制限を使用しない場合は、Schemaを使用しなくてもそんなに違いはないかもしれない
型が間違っているところには静的解析エラーが出るため、以下でもそんなに悪くない気がする

```ts
import { describe, it } from 'vitest'

describe('Schema make struct', () => {
  it('使用しない場合', () => {
    interface typeProduct {
      quantity: string
    }

    const p: typeProduct = {
      quantity: ''
    }
    const p2 = {
      quantity: '',
      a: 123
    }
    const p3: typeProduct = p2
    const p4: typeProduct = {
      quantity: 123
    }
  })
})
```