typescript-is
Advanced tools
Comparing version 0.6.4 to 0.6.5
@@ -57,8 +57,17 @@ /** | ||
/** | ||
* Options for the `AssertParameter` decorator. | ||
*/ | ||
export interface AssertParameterOptions { | ||
/** | ||
* Message that will be passed to the error constructor, in case type assertion fails. | ||
*/ | ||
message?: string; | ||
} | ||
/** | ||
* Creates a type assertion and saves it in the reflection metadata of the method's class. | ||
* Then, when the class is decorated with `ValidateClass`, the method's arguments will be validated. | ||
* | ||
* @param target the class prototype of the method. | ||
* @param propertyKey the method's name. | ||
* @param parameterIndex the index of the parameter in the method's signature. | ||
* @param options options for the decorator. | ||
* Check `AssertParameterOptions` documentation for more. | ||
* | ||
@@ -73,3 +82,3 @@ * @example | ||
*/ | ||
export function AssertParameter(target: object, propertyKey: string | symbol, parameterIndex: number): void; | ||
export function AssertParameter(options?: AssertParameterOptions): (target: object, propertyKey: string | symbol, parameterIndex: number) => void; | ||
@@ -76,0 +85,0 @@ /** |
@@ -9,6 +9,6 @@ require('reflect-metadata'); | ||
function AssertParameter(assertion) { | ||
function AssertParameter(assertion, options = {}) { | ||
return function (target, propertyKey, parameterIndex) { | ||
const assertions = Reflect.getOwnMetadata(assertionsMetadataKey, target, propertyKey) || []; | ||
assertions[parameterIndex] = assertion; | ||
assertions[parameterIndex] = { assertion, options }; | ||
Reflect.defineMetadata(assertionsMetadataKey, assertions, target, propertyKey); | ||
@@ -26,4 +26,4 @@ }; | ||
for (let i = 0; i < assertions.length; i++) { | ||
if (!assertions[i](args[i])) { | ||
throw new errorConstructor('Type assertion failed.'); | ||
if (!assertions[i].assertion(args[i])) { | ||
throw new errorConstructor(assertions[i].options.message || 'Type assertion failed.'); | ||
} | ||
@@ -30,0 +30,0 @@ } |
@@ -6,15 +6,25 @@ "use strict"; | ||
const visitor_1 = require("./visitor"); | ||
function createArrowFunction(accessor, type, visitorContext, isAssert) { | ||
return ts.createArrowFunction(undefined, undefined, [ | ||
ts.createParameter(undefined, undefined, undefined, accessor, undefined, ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)) | ||
], undefined, undefined, ts.createBlock([ | ||
isAssert | ||
? ts.createIf(ts.createLogicalNot(visitor_1.visitType(type, accessor, visitorContext)), ts.createThrow(ts.createNew(ts.createIdentifier('Error'), undefined, [ | ||
ts.createStringLiteral('Type assertion failed.') | ||
])), ts.createReturn(accessor)) | ||
: ts.createReturn(visitor_1.visitType(type, accessor, visitorContext)) | ||
])); | ||
} | ||
function transformDecorator(node, parameterType, visitorContext) { | ||
const decoratorType = visitorContext.checker.getTypeAtLocation(node.expression); | ||
if (decoratorType.symbol.name === 'AssertParameter' | ||
&& path.resolve(decoratorType.symbol.valueDeclaration.getSourceFile().fileName) === path.resolve(path.join(__dirname, '..', '..', 'index.d.ts'))) { | ||
const accessor = ts.createIdentifier('object'); | ||
const expression = ts.createCall(node.expression, undefined, [ | ||
ts.createArrowFunction(undefined, undefined, [ | ||
ts.createParameter(undefined, undefined, undefined, accessor) | ||
], undefined, undefined, ts.createBlock([ | ||
ts.createReturn(visitor_1.visitType(parameterType, accessor, visitorContext)) | ||
])) | ||
]); | ||
return ts.updateDecorator(node, expression); | ||
if (ts.isCallExpression(node.expression)) { | ||
const signature = visitorContext.checker.getResolvedSignature(node.expression); | ||
if (signature !== undefined | ||
&& signature.declaration !== undefined | ||
&& path.resolve(signature.declaration.getSourceFile().fileName) === path.resolve(path.join(__dirname, '..', '..', 'index.d.ts')) | ||
&& node.expression.arguments.length <= 1) { | ||
const accessor = ts.createIdentifier('object'); | ||
const arrowFunction = createArrowFunction(accessor, parameterType, visitorContext, false); | ||
const expression = ts.updateCall(node.expression, node.expression.expression, undefined, [arrowFunction].concat(node.expression.arguments)); | ||
return ts.updateDecorator(node, expression); | ||
} | ||
} | ||
@@ -37,20 +47,12 @@ return node; | ||
const name = visitorContext.checker.getTypeAtLocation(signature.declaration).symbol.name; | ||
const create = name === 'createIs' || name === 'createAssertType'; | ||
const assert = name === 'assertType' || name === 'createAssertType'; | ||
const isCreate = name === 'createIs' || name === 'createAssertType'; | ||
const isAssert = name === 'assertType' || name === 'createAssertType'; | ||
const typeArgument = node.typeArguments[0]; | ||
const type = visitorContext.checker.getTypeFromTypeNode(typeArgument); | ||
const accessor = ts.createIdentifier('object'); | ||
if (!(create && node.arguments.length === 0) && !(!create && node.arguments.length === 1)) { | ||
if (!(isCreate && node.arguments.length === 0) && !(!isCreate && node.arguments.length === 1)) { | ||
throw new Error('Calls to `is` and `assertType` should have one argument, calls to `createIs` and `createAssertType` should have no arguments.'); | ||
} | ||
const arrowFunction = ts.createArrowFunction(undefined, undefined, [ | ||
ts.createParameter(undefined, undefined, undefined, accessor, undefined, ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)) | ||
], undefined, undefined, ts.createBlock([ | ||
assert | ||
? ts.createIf(ts.createLogicalNot(visitor_1.visitType(type, accessor, visitorContext)), ts.createThrow(ts.createNew(ts.createIdentifier('Error'), undefined, [ | ||
ts.createStringLiteral('Type assertion failed.') | ||
])), ts.createReturn(accessor)) | ||
: ts.createReturn(visitor_1.visitType(type, accessor, visitorContext)) | ||
])); | ||
if (create) { | ||
const arrowFunction = createArrowFunction(accessor, type, visitorContext, isAssert); | ||
if (isCreate) { | ||
return arrowFunction; | ||
@@ -57,0 +59,0 @@ } |
{ | ||
"name": "typescript-is", | ||
"version": "0.6.4", | ||
"version": "0.6.5", | ||
"engines": { | ||
@@ -5,0 +5,0 @@ "node": ">=6.14.4" |
@@ -169,5 +169,5 @@ # typescript-is | ||
@ValidateClass | ||
@ValidateClass() | ||
class A { | ||
method(@AssertParameter value: number) { | ||
method(@AssertParameter() value: number) { | ||
// You can safely use value as a number | ||
@@ -174,0 +174,0 @@ return value; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
71551
737