hoeck / simple-runtypes

Small, efficient and extendable runtype library for Typescript
MIT License
114 stars 5 forks source link

Incorrect error message for invalid keys in a `record` #91

Closed remnantkevin closed 1 year ago

remnantkevin commented 1 year ago

The error message that is shown when a record runtype finds invalid keys is incorrect.

As far as I can see this bug was introduced in v7.0.0, specifically in commit 14bac166c.

Below are examples showing the incorrect error message in the current version (v7.1.2). See reproduction on replit.

import * as st from "simple-runtypes"

const recordRT = st.record({
  a: st.string()
})

console.log(st.use(recordRT, { a: "ay" }))
// => { ok: true, result: { a: 'ay' } }

const result1 = st.use(recordRT, { a: "ay", b: "bee" })
console.log(result1)
// => {
//      ok: false,
//      error: {
//        reason: 'invalid keys in record [{"a":"ay","b":"bee"}]',
//        path: [],
//        value: { a: 'ay', b: 'bee' },
//        [Symbol(SimpleRuntypesFail)]: true
//      }
//    }
console.log(st.getFormattedError(result1.error)) // (A)
// => invalid keys in record [{"a":"ay","b":"bee"}] at `<value>` for `{"a":"ay","b":"bee"}`

const nestedRecordRT = st.record({ 
  a: st.string(),
  b: st.record({ 
    c: st.string()
  })
})

console.log(st.use(nestedRecordRT, { a: "ay", b: { c: "cee" } }))
// => { ok: true, result: { a: 'ay', b: { c: 'cee' } } }

const result2 = st.use(nestedRecordRT, { a: "ay", b: { c: "cee", d: "dee" } })
console.log(result2)
// => {
//      ok: false,
//      error: {
//        reason: 'invalid keys in record [{"c":"cee","d":"dee"}]',
//        path: [ 'b' ],
//        value: { a: 'ay', b: [Object] },
//        [Symbol(SimpleRuntypesFail)]: true
//      }
//    }
console.log(st.getFormattedError(result2.error)) // (B)
// => invalid keys in record [{"c":"cee","d":"dee"}] at `<value>.b` for `{"c":"cee","d":"dee"}`

const result3 = st.use(nestedRecordRT, { a: "ay", b: { c: "cee" }, e: "eee" })
console.log(result3)
// => {
//      ok: false,
//      error: {
//        reason: 'invalid keys in record [{"a":"ay","b":{"c":"cee"},"e":"eee"}]',
//        path: [],
//        value: { a: 'ay', b: [Object], e: 'eee' },
//        [Symbol(SimpleRuntypesFail)]: true
//      }
//    }
console.log(st.getFormattedError(result3.error)) // (C)
// => invalid keys in record [{"a":"ay","b":{"c":"cee"},"e":"eee"}] at `<value>` for `{"a":"ay","b":{"c":"cee"},"e":"eee"}`

The error messages should read:

(A) invalid keys in record ["b"] at `<value>` for `{"a":"ay","b":"bee"}`
(B) invalid keys in record ["d"] at `<value>.b` for `{"c":"cee","d":"dee"}`
(C) invalid keys in record ["e"] at `<value>` for `{"a":"ay","b":{"c":"cee"},"e":"eee"}`
hoeck commented 1 year ago

@remnantkevin massive thanks for identifying, fixing and describing this bug! great work :heart:

To be honest, I had noticed that something is off but (guess you know it) was too occupied at work to look into it :disappointed:.