Nano "Typescript" without compilation
Eckehard

Eckehard @efpage

About: Always curious...

Location:
Germany
Joined:
May 24, 2021

Nano "Typescript" without compilation

Publish Date: Mar 28 '24
8 10

Thanks to this post from Toby Farley (Shadow Chicken), I had an inspiration to build my own tiny little nano "typescript" running without compilation.

Ok, typescript provides much more, but if you only need some typechecks, this little routine would do the trick:

/* ==================================================
    Nano typeCheck
    Valid types
    "var": Variant - all types allowed 
    "string"
    "number"
    "bigInt"
    "boolean"
    "object"
    "array"
    "date"
    "set"
    "function"
  ================================================== */
  function typeCheck(v) {
  if ((typeof v) !== "object") throw (`Parameter must be Object in function ${typeCheck.caller.name}`)

  // Build return value array
  let res = Object.entries(v).map((a, i) => {
    let [typ, val] = a;  // get key/values
    typ = typ.charAt(0).toUpperCase() + typ.slice(1) // Capitalize
    if (typ === "Var")  // Variant type
      return val
    if (val.constructor.name !== typ) // check type
      throw (`Type error parameter ${i + 1} is not ${typ} in function ${typeCheck.caller.name}`)
    return (val)
  })
  return res
}

function myFunc(a,b,c,d) {
  typeCheck({ string: a, boolean: b, array: c, var: d })
  console.log(a)
  console.log(b)
  console.log(c)
  console.log(d)
}

myFunc( "5",  true, [1, 2, 3, 4, 5], "Do what you want")
Enter fullscreen mode Exit fullscreen mode

You can also submit typ declaration with the parameters like this:

function myFunc(pars) {
  let [a, b, c, d] = typeCheck(pars)
  console.log(a)
  console.log(b)
  console.log(c)
  console.log(d)
}

myFunc({ string: "5", boolean: true, array: [1, 2, 3, 4, 5], var: "Do what you want" })
Enter fullscreen mode Exit fullscreen mode

Types can be named using the standard type names with lower or upper case, so both would be accepted:

{ string: a, boolean: b, array: c, var: d }
{ String: a, Boolean: b, Array: c, Var: d }
Enter fullscreen mode Exit fullscreen mode

Tell me, what you think.

P.S.: This post was changed after the first sumbission to show different ways of usage.

Comments 10 total

  • Alex Lohr
    Alex LohrMar 28, 2024

    The main benefit of Typescript is that it catches type unsoundness in development without the need to add code to the production bundle.

    Checking types in production is the field of scheme libraries. While your solution is interesting as an example, it cannot compete with scheme libraries like valibot or zod.

    • Eckehard
      EckehardMar 28, 2024

      Be serious: does it look like the next big thing? It's just an example, but I like the sceme....

      • Alex Lohr
        Alex LohrMar 28, 2024

        No, not really. I just wanted to point out that this is something different than TypeScript and that others have found a niche for similar solutions that even work very well together with TypeScript.

  • artydev
    artydevMar 28, 2024

    Nice, but I agree with Alex, at runtime, zod is a must

  • Rudransh Bhardwaj
    Rudransh BhardwajMar 29, 2024

    wow !!
    this is awesome !!
    I think it's already very great
    you can add more unique features
    it can be next big thing

    nice

  • artydev
    artydevApr 29, 2024

    Hy Eckehard, look at this :

    for (let value of [
            "Array", "Boolean", "Date", "Element",
            "Error", "Function", "Map", "Node",
            "Number", "RegExp", "Set", "String",
            "Symbol", "Text"
        ]) Object.defineProperty(
            window[value].prototype, "__type", { value }
        );
    
    Enter fullscreen mode Exit fullscreen mode

    from Jason Knight DomJon

    • Eckehard
      EckehardApr 29, 2024

      Looks interesting, but - how to use it?

      • artydev
        artydevApr 30, 2024
        for (let value of [
                "Array", "Boolean", "Date", "Element",
                "Error", "Function", "Map", "Node",
                "Number", "RegExp", "Set", "String",
                "Symbol", "Text", "Object"
            ]) Object.defineProperty(
                window[value].prototype, "__type", { value }
        );
        
        
        let a =  []
        let b = {}
        let c = () => 1
        
        console.log(a.__type)
        console.log(b.__type)
        console.log(c.__type)
        
        Enter fullscreen mode Exit fullscreen mode

        Look here demo

        • Eckehard
          EckehardApr 30, 2024

          Ok, this boils down to changing.

          val.constructor.name
          val.__type
          
          Enter fullscreen mode Exit fullscreen mode

          which is slightly faster. But most time in my initial routine is wasted capitalizing the keywords, which is just for convennience:

          typ = typ.charAt(0).toUpperCase() + typ.slice(1) // Capitalize
          
          Enter fullscreen mode Exit fullscreen mode

          You can skip this line, if all types are written in uppercase.

  • artydev
    artydevApr 30, 2024

    Eckehard,

    Here is what Phind AI, propose for your code Demo:

    for (let value of [
        "Array", "Boolean", "Date", "Element",
        "Error", "Function", "Map", "Node",
        "Number", "RegExp", "Set", "String",
        "Symbol", "Text"
    ]) {
        if (window[value]) { 
            Object.defineProperty(
                window[value].prototype, "__type", {
                    value: value,
                    writable: false, 
                    enumerable: false, 
                    configurable: false 
                }
            );
        }
    }
    
    function typeCheck(inputObject) {
    
        if (typeof inputObject !== "object") {
            throw new Error(`Parameter must be Object in function ${typeCheck.caller.name}`);
        }
    
        const checkedValues = Object.entries(inputObject).map(([typeKey, value], index) => {
            const capitalizedTypeKey = typeKey.charAt(0).toUpperCase() + typeKey.slice(1);
            if (capitalizedTypeKey === "Var") {
                return value;
            }
            const actualType = value.__type || typeof value;
            if (actualType !== capitalizedTypeKey) {
                throw new Error(`Type error parameter ${index + 1} is not ${capitalizedTypeKey} (expected ${capitalizedTypeKey}, got ${actualType}) in function ${typeCheck.caller.name}`);
            }
            return value;
        });
    
        return checkedValues;
    }
    
    function myFunc(pars) {
      let [a, b, c, d] = typeCheck(pars)
      console.log(a)
      console.log(b)
      console.log(c)
      console.log(d)
    }
    
    myFunc({ string: "5", boolean: true, array: [1, 2, 3, 4, 5], var: "Do what you want" })
    
    Enter fullscreen mode Exit fullscreen mode
Add comment