I read @nadako abstract blog post and in Use case: object identifiers
he note that their is no type checking for typedef(I.e MyTypedef ->Int->Void function can accept simple int for MyTypedef argument), why?
Example: Try Haxe !
Typedefs don’t remove type checking, it’s just that they aren’t a new type, only a named alias.
typedef A = Int;
typedef B = Int;
function main () {
var a : A = 5;
var b : B = 6;
test(a);
test(b);
test(12);
}
function test (i:Int) {}
This compiles because it says that var a and b are of type Int, here called through a “nickname” but still Int.
Abstracts are different, they are a new type and therefor don’t unify Unification - Haxe - The Cross-platform Toolkit unless they have to/from functions to do so Implicit Casts - Haxe - The Cross-platform Toolkit.
I understand that, but if I decided to let test
function get MyTypedef
argument, so this is should be only MyTypedef
, this is probably should not match as regular Int
, you can give me example of function that get MyTypedef
but you also might want to pass it a regular Int?
I’m not sure but maybe if typedef include this kind of typedef things will get messy with objects? i.e:
function test(obj:{a:String, b:Int}) {}
typedef MyTypedef = {a:String, b:Int}
public function new () {
var obj:MyTypedef = {a:"test", b:1};
test(obj); // OK
test({a:"test", b:1}); // Will cause error
}
The thing is that MyTypedef
isn’t exactly a type, it’s a type alias. You’re not saying that the test function takes a MyTypedef
argument but an Int
, you’re just using an alternate name for it.
(that’s a bit of an oversimplification but it’s easier to understand like that)
Typedefs over primitive types shouldn’t be that common since there’s not a lot of use for that,
one use case is shortening function type:
typedef SuccessCallback = Int->Int->Void;
typedef ErrorCallback = String->Void;
function doProcess(onSuccess:SuccessCallback, onError:ErrorCallback):Void {}
Another use case is having different implementations:
#if js
typedef TheClass = mypackage.impl.js.TheClass;
#elseif java
typedef TheClass = mypackage.impl.java.TheClass;
#end
Those wouldn’t work it typedef didn’t allow anything that matches it.
If you want a runtime Int
that doesn’t unify with an Int
at compile time then you need to do what’s described in the blog post:
abstract MyUnrelatedType (Int) {}