157

I meant to write a parameter of type number, but I misspelled the type, writing Number instead.

On my IDE (JetBrains WebStorm) the type Number is written with the same color that is used for the primitive type number, while if I write a name of a class (known or unknown) it uses a different color, so I guess that somehow it recognizes the misspelled type as a correct/almost-correct/sort-of-correct type.

When I compile the code, instead of complaining for example that the compiler couldn't found a class named Number, TSC writes this error message:

Illegal property access

Does that mean that number and Number both co-exists as different types?

If this is true, which is the difference between those classes?

If this is not the case, then why it simply didn't write the same error message it displays for unknown classes ("The name 'Number' does not exist in the current scope")

This is the code:

class Test
{
    private myArray:string[] = ["Jack", "Jill", "John", "Joe", "Jeff"];

    // THIS WORKS
    public getValue(index:number):string
    {
        return this.myArray[index];
    }

    // THIS DOESN'T WORK: ILLEGAL PROPERTY ACCESS
    public getAnotherValue(index:Number):string
    {
        return this.myArray[index]; 
    }
}
MiMo
  • 11,793
  • 1
  • 33
  • 48
Cesco
  • 3,770
  • 7
  • 24
  • 26

3 Answers3

194

To augment Ryan's answer with guidance from the TypeScript Do's and Don'ts:

Don't ever use the types Number, String, Boolean, Symbol, or Object These types refer to non-primitive boxed objects that are almost never used appropriately in JavaScript code.

/* WRONG */
function reverse(s: String): String;

Do use the types number, string, boolean, and symbol.

/* OK */
function reverse(s: string): string;
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
  • But typescript documentation says Object. https://www.typescriptlang.org/docs/handbook/basic-types.html – atilkan May 09 '18 at 15:16
  • 2
    @atilkan That's fun. I guess they aren't taking their own advice. – Shaun Luttin May 09 '18 at 16:24
  • 2
    That documentation was written before lower-case `object` was a thing – Ryan Cavanaugh May 10 '18 at 23:32
  • 1
    @RyanCavanaugh Guess we should report this. – atilkan May 11 '18 at 12:13
  • 3
    @ShaunLuttin What about array, i can't find any lowercase example. – atilkan May 11 '18 at 12:25
  • 3
    @atilkan You should probably be using `[]` to denote array types. There might be exceptions though, I'm not sure. – Victor Zamanian Oct 12 '18 at 09:42
  • 1
    @VictorZamanian There is a good explanation here -> https://toddmotto.com/typing-arrays-typescript – atilkan Oct 12 '18 at 15:50
  • If you do this: `console.log(number);`, the typescript compiler will warn you "number only refers to a type, ...", but `console.log(Number);` is fine. – ckybonist Mar 18 '19 at 07:42
  • 1
    @KuanYuChu this happens if you have no `number` identifier in scope. If you declare `let number = 1` then the warning disappears, since `number` now refers to that variable. You would get the same behaviour if you declare `interface MyInterface` and try to do `console.log(MyInterface)` - a warning that it's a type, not a concrete thing that exists. However, `Number` is a function that always exists in JS, so it's always in scope. – VLAZ May 17 '19 at 12:24
  • This is such an easy mistake to make. Do you know of any eslint rules, ts configs, or similar that help prevent devs from making this mistake? – pir Dec 01 '21 at 08:54
  • Found https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/ban-types.md in case anyone's interested :) – pir Dec 01 '21 at 08:58
  • But in Vue.js, variables are declared with these capitalized types, like in `prop` variable is declared like `message: String` – CDT Oct 29 '22 at 00:55
78

JavaScript has the notion of primitive types (number, string, etc) and object types (Number, String, etc, which are manifest at runtime). TypeScript types number and Number refer to them, respectively. JavaScript will usually coerce an object type to its primitive equivalent, or vice versa:

var x = new Number(34);
> undefined
x
> Number {}
x + 1
> 35

The TypeScript type system rules deal with this (spec section 3.7) like this:

For purposes of determining subtype, supertype, and assignment compatibility relationships, the Number, Boolean, and String primitive types are treated as object types with the same properties as the ‘Number’, ‘Boolean’, and ‘String’ interfaces respectively.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Ryan Cavanaugh
  • 209,514
  • 56
  • 272
  • 235
  • 8
    One might add that they are not exactly cross assignable: http://www.typescriptlang.org/Playground/#src=var%20x%3Anumber%3B%0Avar%20y%3ANumber%3B%0Ay%20%3D%20x%3B%20%2F%2F%20okay%20%0Ax%20%3D%20y%3B%20%2F%2F%20not%20okay%20 – basarat Mar 19 '13 at 02:08
  • 7
    Also to answer the original poster : Yes TSC (like javascript) is case sensitive :) – basarat Mar 19 '13 at 05:20
2

As the TypeScript doc says:

var Number: NumberConstructor
(value?: any) => number

An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.

As it says, take any as parameter and return number or null

It give an easy way to check a value is number or not

Number("1234");   // 1234
Number("1234.54") // 1234.54
Number("-1234.54") // -1234.54
Number("1234.54.33") // null
Number("any-non-numeric") // null

So simply we can use to check the number, like:

if(Number(val)){
   console.log('val is a number');
} else {
   console.log('Not a number');
}
Ali Adravi
  • 21,707
  • 9
  • 87
  • 85