Created
January 29, 2017 11:06
-
-
Save JohnWeisz/beb7b4dadc512be30ce6c7c1e4c7e652 to your computer and use it in GitHub Desktop.
TypeScript runtime checked type-assertion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export declare interface RuntimeAssert | |
{ | |
any?: (value: any) => { | |
asNumber: () => number, | |
asArrayOfNumber: () => number[], | |
asString: () => string, | |
asArrayOfString: () => string[], | |
asBoolean: () => boolean, | |
asArrayOfBoolean: () => boolean[], | |
as: <T>(ctor: new (...args: any[]) => T) => T, | |
asArrayOf: <T>(ctor: new (...args: any[]) => T) => T[] | |
}; | |
// Primitives. | |
(value: number): { asNumber: () => number }; | |
(value: string): { asString: () => string }; | |
(value: boolean): { asBoolean: () => boolean }; | |
// Arrays of primitives. | |
(value: number[]): { asArrayOfNumber: () => number[] }; | |
(value: string[]): { asArrayOfString: () => string[] }; | |
(value: boolean[]): { asArrayOfBoolean: () => boolean[] }; | |
// Unions of primitives. | |
(value: number | string): { asNumber: () => number, asString: () => string }; | |
(value: number | boolean): { asNumber: () => number, asBoolean: () => boolean }; | |
(value: string | boolean): { asString: () => string, asBoolean: () => boolean }; | |
// Arrays of unions of primitives. | |
(value: (number | string)[]): { asArrayOfNumber: () => number[], asArrayOfString: () => string[] }; | |
(value: (number | boolean)[]): { asArrayOfNumber: () => number[], asArrayOfBoolean: () => boolean[] }; | |
(value: (boolean | string)[]): { asArrayOfBoolean: () => boolean[], asArrayOfString: () => string[] }; | |
// Object values. | |
<T extends Function>(value: T): { as: (ctor: FunctionConstructor) => T }; | |
<B>(value: B[]): { | |
asArrayOf: <T extends B>(ctor: new (...args: any[]) => T) => T[], | |
asArrayOfAbstract: (ctor: Function) => B[] | |
}; | |
<B>(value: B): { | |
as: <T extends B>(ctor: new (...args: any[]) => T) => T, | |
asAbstract: (ctor: Function) => B | |
}; | |
} | |
//var t1: EventTarget; | |
//var t2: EventTarget; | |
//var _t1 = assert(t1).as(HTMLInputElement); | |
//var _t2 = assert(t2).as(Date); | |
export var assert: RuntimeAssert = ((value: any): any => | |
{ | |
var _assertionObj = { | |
as: (ctor: new (...args: any[]) => any) => | |
{ | |
if (value === null) | |
return value; | |
if (typeof value === "undefined") | |
return value; | |
if (value instanceof ctor) | |
return value; | |
else | |
throw new TypeError(`Type '${acquireTypeName(value)}' is not assignable to type '${ctor.name}'.`); | |
}, | |
asAbstract: (ctor: Function) => | |
{ | |
return _assertionObj.as(ctor as any); | |
}, | |
asArrayOf: (ctor: new (...args: any[]) => any) => | |
{ | |
if (value instanceof Array) | |
{ | |
if (value.length > 0 && value.some(item => !(item instanceof ctor))) | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value[0])}[]' is not assignable to type '${ctor.name}[]'.`); | |
} | |
return value; | |
} | |
else | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value)}' is not assignable to type '${ctor.name}[]'.`); | |
} | |
}, | |
asNumber: () => | |
{ | |
if (value instanceof Number || typeof value === "number") | |
return value; | |
else if (typeof value === "undefined") | |
return 0; | |
else | |
throw new TypeError(`Type '${acquireTypeName(value)}' is not assignable to type 'number'.`); | |
}, | |
asArrayOfNumber: () => | |
{ | |
if (value instanceof Array) | |
{ | |
if (value.length > 0 && value.some(item => (!(item instanceof Number) && typeof item !== "number"))) | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value[0])}[]' is not assignable to type 'number[]'.`); | |
} | |
return value; | |
} | |
else | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value)}' is not assignable to type 'number[]'.`); | |
} | |
}, | |
asString: () => | |
{ | |
if (value instanceof String || typeof value === "string") | |
{ | |
return value; | |
} | |
else if (typeof value === "undefined") | |
{ | |
return ""; | |
} | |
else | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value)}' is not assignable to type 'string'.`); | |
} | |
}, | |
asArrayOfString: () => | |
{ | |
if (value instanceof Array) | |
{ | |
if (value.length > 0 && value.some(item => (!(item instanceof String) && typeof item !== "string"))) | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value[0])}[]' is not assignable to type 'string[]'.`); | |
} | |
return value; | |
} | |
else | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value)}' is not assignable to type 'string[]'.`); | |
} | |
}, | |
asBoolean: () => | |
{ | |
if (value instanceof Boolean || typeof value === "boolean") | |
{ | |
return value; | |
} | |
else if (typeof value === "undefined") | |
{ | |
return false; | |
} | |
else | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value)}' is not assignable to type 'boolean'.`); | |
} | |
}, | |
asArrayOfBoolean: () => | |
{ | |
if (value instanceof Array) | |
{ | |
if (value.length > 0 && value.some(item => (!(item instanceof Boolean) && typeof item !== "boolean"))) | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value[0])}[]' is not assignable to type 'boolean[]'.`); | |
} | |
return value; | |
} | |
else | |
{ | |
throw new TypeError(`Type '${acquireTypeName(value)}' is not assignable to type 'boolean[]'.`); | |
} | |
} | |
}; | |
return _assertionObj; | |
}); | |
assert.any = assert as any; | |
function acquireTypeName(value: any) | |
{ | |
var typeofValue = typeof value; | |
if (typeofValue === "object") | |
{ | |
if (value === null) | |
{ | |
return "null"; | |
} | |
else | |
{ | |
return value.constructor.name; | |
} | |
} | |
else | |
{ | |
return typeofValue; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment