canjs / can-observable-mixin

Define properties on JavaScript classes
https://canjs.com
MIT License
2 stars 1 forks source link

Type errors obscure real errors #147

Closed phillipskevin closed 4 years ago

phillipskevin commented 4 years ago

This code catches all errors that happen when a property is set: https://github.com/canjs/can-observable-mixin/blob/fa5a085a9bed861175adc63f5dc7d230b584807c/src/define.js#L694-L702

So if you have some code like this:

import { ObservableObject, type, Observation, Reflect } from "//unpkg.com/can/core.mjs"

class T extends ObservableObject {
  static props = {
    m: {
      type: type.maybe(String),
      default: "Hi"
    },
    get bigM () {
      return this.m.toUpperCase()
    }
  }
}

const t = new T()
const obs = new Observation(() => t.bigM)
Reflect.onValue(obs, ({ value }) => {
  console.log(`t.bigM: ${t.bigM}`)
})

t.m = null

You get an error like:

Uncaught Error: "null" (object) is not of type String. Property m is using "type: String". Use "m: type.convert(String)" to automatically convert values to Strings when setting the "m" property.

When the real error is:

TypeError: Cannot read property 'toUpperCase' of null

phillipskevin commented 4 years ago

Here's a codepen: https://codepen.io/kphillips86/pen/QWWqJXp?editors=0010

m-mujica commented 4 years ago

Just got a fun one. With code like:

const NumberOrString = val => val;

class Node extends ObservableObject {
  static get props() {
    return {
      key: type.convert(NumberOrString)
    };
  }
}

new Node({ key: {} });

I get the following error:

Error: "[object Object],[object Object]" (object) is not of type NumberOrString. Property key is using "type: NumberOrString". Use "key: type.convert(NumberOrString)" to automatically convert values to NumberOrStrings when setting the "key" property.
    at ParsedJSONNode.set Node{}.key (http://127.0.0.1:5501/node_modules/can-observable-mixin/src/define.js:705:15)
    at Object.eval (http://127.0.0.1:5501/node_modules/can-observable-mixin/src/define.js:1084:14)
    at String.eval (http://127.0.0.1:5501/node_modules/can-reflect/reflections/shape/shape.js:517:21)

The real error is that arrow functions cannot be used on the right side of typeof:

var Type = () => {};
var o = {};

o instanceof Type // TypeError: Function has non-object prototype 'undefined' in instanceof check

Type converters cannot be arrow functions.