3

Example:

function action(value) {
     // I want to operate on a string
     String(value)...;
}

When we pass dynamic values into JavaScript's primary types (String, Number, Boolean, Object, etc.) we can (for want of a better word) cast the value to the specified type.

Is it possible to build this feature in custom types, and how would I go about this?

Example of what I would like to do:

function action(value) {
    Point(value)...;
    // Value at this point (excuse the pun) is a point
    // // *** Would like to see that intellisense is aware of the type at this point, but please don't assume this is ONLY for intellisense***
}

Is it possible to call constructor functions in this way and have the constructor function "cast" the value to an instance of itself - or does this only work for JavaScript's primary types?

8
  • it depends on the constructor parameter, if it can take a param of type string, int, etc then yes its possible Commented Jul 2, 2015 at 23:52
  • No, but you can create an object using var o = Object.create(Point.prototype) and then copy value into it. You can apply the constructor to it as well. Point.call(o) Commented Jul 2, 2015 at 23:52
  • maybe your team is interested in TypeScript typescriptlang.org Commented Jul 2, 2015 at 23:53
  • ...There are ECMAScript 6 features that allow more flexibility in this regard. Commented Jul 2, 2015 at 23:53
  • You need to assign the result of the functions to something, e.g. value = Point(value). Commented Jul 2, 2015 at 23:53

2 Answers 2

3

Your custom constructor can just examine the typeof the arguments that it is passed and behave accordingly. This isn't technically a "cast", but rather writing code to examine the types of the arguments and then decide on the proper behavior which can include converting from one type to another.

See How to overload functions in javascript? for a much longer description of how to examine arguments sent to any function and then adjust the behavior of the function based on the type and position and presence of the arguments. This same functionality can be used to do something that is "cast" like (though we don't usually think of casting in Javascript, but rather just converting).

We could give you actual code examples if you can be more specific about what types you want to "cast" in your Point constructor.

There are some simple examples of "cast" like things:

function delay(fn, t) {
    // if t is passed as a string represeantation of a number, 
    // convert it to an actual number
    return setTimeout(fn, +t);
}

Or, a little more interesting example that can take a number of ms, a string with units at the end or an object with properties:

function delay(fn, t) {
    var typeT = typeof t, ms, matches, num, multiplier,
        suffixes = {ms: 1, sec: 1000, min: 1000 * 60, hr: 1000 * 60 * 60};
    if (typeT === "string") {
        matches = t.match(/^([\d.]+)(.+)$/);
        if (matches) {
            num = +matches[1];
            multiplier = suffixes[matches[2]];
            if (multiplier) {
                ms = num * multiplier;
            }
        }
    } else if (typeT === "number") {
        // plain number is milliseconds
        ms = t;
    } else if (typeT === "object" && t.units && t.value) {
        multiplier = suffixes[t.units];
        if (multiplier) {
           ms = t.value * multiplier;
        }            
    }
    if (ms === undefined) {
        throw new Error("Invalid time argument for delay()");
    }
    return setTimeout(fn, ms);
}


delay(myFn, "2.5hr");
delay(myFn, "25sec");
delay(myFn, 150);
delay(myFn, {units: "sec", value: 25});
Sign up to request clarification or add additional context in comments.

8 Comments

Better copy it as a local variable e.g var localT = +t; to avoid overwriting arguments.
@SebastianNette - there's no overwriting to be worried about here. The argument t is already local to this function so there's no need to create yet another local variable.
t = +t overwrites arguments[1] which shouldn't be done, afaik (skips internal optimizations).
"we don't usually think of casting in Javascript, but rather just converting". Absolutely. Variables are typeless, values have a Type (which often isn't related to the value returned by typeof). Anything returned by a constructor has a Type of Object, however that's pretty useless. Usually constructor is more informative, but unreliable.
@SebastianNette - that depends upon what you're optimizing for and what optimizations the exact JS engine is capable of. Are you seriously saying that it is worth adding an extra local variable declaration in a function this simple that has no performance importance? Or, are you just applying some blanket suggestion that doesn't really have any consequence in this specific example?
|
1

If you are serious about type enforcing (and there is a lot of good reasons to be)... and you want to continue to use Javascript... maybe you should give a try to TypeScript

It enforces type checking and compiles down to Javascript Which gives you the option to publish the TypeScript for inline compilation...

Or if you intent a bit for your work (like me)... you can develop a project and spit-out the Javascript before uploading... in this phase you can optimize the 'thing'... pass a Linter, a Minifier and a Obfuscator... and you'll get highly optimized and a bit protected piece of code (if we are talking about client-side of course, at server side no obfuscation is advised).

Another BIG-BIG-BIG advantage (to me at least) is that you can use the best Intellitype/Intellisense/Refactor IDE (VS 2013R4 CE) which is free.

See here the last features in TypeScript... TypeScript at Build/2014 by Anders Hejlsberg (channel9)

ZEE

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.