Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at cf.Objective() 2009 (Minneapolis, MN) with: Pete Freitag
Ben Nadel at cf.Objective() 2009 (Minneapolis, MN) with: Pete Freitag@pfreitag )

Using ANY Type Prevents Function Parameter Type-Checking In TypeScript 2.1.5

By Ben Nadel on

I've been really enjoying TypeScript for its self-documentation nature and the way it forces me to think about data consumption within my application; but, I wouldn't say that I really understand TypeScript. Not yet. Every few days, I find myself tripping over some feature or caveat of the language. Just yesterday, I couldn't figure out why type-checking wasn't working for a particular method invocation; and, it wasn't until I read this issue over on GitHub that I learned that using an "any" type value - explicitly or implicitly - opts-out of function parameter type-checking in TypeScript.


 
 
 

 
 
 
 
 

Run this demo in my JavaScript Demos project on GitHub.

Normally, in TypeScript, if you define a function signature that accepts a certain type, such a String:

function( value: string )

... then, any attempt to pass-in a non-String value during function invocation should raise a type-checking error. But, it turns out, if the value that you're passing into the function is of type "any", then TypeScript does not enforce the type validation on the function parameter.

Now, that doesn't mean that the type constraint on the function parameter becomes useless - it's still used by TypeScript to validate the consumption of the argument within the body of the function. TypeScript just won't guarantee that the incoming value is actually the type defined by the function signature.

To see this in action, I've created a tiny demo in which we have a function that accepts a String argument and logs a few values to the console. I then attempt to invoke this function passing in a few different types:

  • String
  • Boolean
  • Any (explicitly up-cast from Date)

Let's look at the code:

  • // Passing a string to an :string argument.
  • logString( "I am a String" );
  •  
  • // Passing a Boolean to a :string argument - this will raise a type-checking error.
  • logString( true );
  •  
  • // Passing an ANY to a :string argument - this will NOT RAISE a type-checking error
  • // because ANY essentially "opts out" of type-checking.
  • // --
  • // Read More: https://github.com/Microsoft/TypeScript/issues/9999
  • logString( <any>( new Date() ) );
  •  
  • // ----------------------------------------------------------------------------------- //
  • // ----------------------------------------------------------------------------------- //
  •  
  • function logString( value: string ) : void {
  •  
  • if ( value.toLowerCase ) {
  •  
  • console.log( value.toLowerCase() );
  •  
  • }
  •  
  • // Even if we pass-in an ANY type, opting out of parameter type checking, the
  • // :string type is still used to validate the parameter / value consumption
  • // within the function body itself. As such, this guard statement will raise a
  • // type-checking error because .getTime() is NOT a property of a String.
  • if ( value.getTime ) {
  •  
  • console.log( value.getTime() );
  •  
  • }
  •  
  • }

Within the body of the function, you can see that I'm referencing two value properties: .toLowerCase() and .getTime(). The .toLowerCase() value is expected on a String; but, the .getTime() is not - it's a property of Date. I'm including the latter property in order to demonstrate that the String paremeter is still type-checked within the body of the function, even if the incoming value is not always validated.

When we run this code, we get the following output:


 
 
 

 
 TypeScript doesn't type-check  
 
 
 

As you can see, TypeScript raised a type-checking error when we attempted to pass "true" - a Boolean - into a function that expected a String. But, it did not raise a type-checking error when we passed <any>Date into the function. This is because the up-casting of the Date to an "Any type" essentially opts-out of type-checking for the function parameter. That said, we can see that TypeScript still uses the function parameter type annotation to validate the consumption of the argument within the body of the function.

Since TypeScript is still validating the argument within the context of the function, I don't think this behavior is such a big deal. Of course, you can always down-cast an "any" value to a concrete value before invoking the given function and TypeScript will validate the function invocation. That said, it's good to know that this "opt-out of type checking" behavior exists in TypeScript when dealing with "any" types.



Looking For A New Job?

Ooops, there are no jobs. Post one now for only $29 and own this real estate!

100% of job board revenue is donated to Kiva. Loans that change livesFind out more »

Reader Comments

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.