zLupim
zLupim

Reputation: 339

Is it possible to create a new data type in JavaScript?

Is it possible to create a new data type in JavaScript, like string?

Example: I have the variable person and I want to declare that the type of that variable is Person.

Like this:

var person = "idk"
console.log(typeof person) 

Output: "Person"

Upvotes: 30

Views: 9190

Answers (7)

Jérôme Beau
Jérôme Beau

Reputation: 11450

You can define custom types as classes since ECMASCript 2015 (ES6):

class Person {
  static get type() {
    return Person.prototype.constructor.name
  }
  get type() {
    return this.constructor.name
  }
  isA(clazz) {
    return this.type === clazz.type 
  }
}

const john = new Person();
if (john.isA(Person)) {
  console.log('John is a person')
}

then you can also define your own typeOf() function:

const typeOf = (obj) => obj.type

console.log(typeOf(person))  // Prints 'Person' 

Upvotes: 0

LiuXiMin
LiuXiMin

Reputation: 1265

In world of JavaScript, type is not same as other OOP languages.

And there is a subtle difference between ECMA and JavaScript:

In latest ECMA, there is only eight data types: Undefined, Null, Boolean, String, Symbol, Number, BigInt, and Object.

That is to say, ECMA treats Function as one subtype of Object.

In JavaScript, we almost always treat Function as one separate type, because typeof (function(){}) gives us function. However, typeof [] will give us array, so we treat Array as one subtype of object, same thing happens to Set, Map, Date, ..., these data may exist as one separate type in some OOP language, such as Python, but in JavaScript, they are all subtype of Object.

So, this is the real situation we face when talking about type in JavaScript.

But, if don't only focus on typeof, we have better way to create and detect our new data type in JavaScript.

Speak accurately, we can create our new data subtype, sub Object type, and we should also detect subtype of data in JavaScript in most cases.

Key thing is Object.prototype.toString and symbol.toStringTag.

Below is demo code:

function Person() {
}

const person = new Person()
const getObjTag = (obj) => Object.prototype.toString.call(obj).slice(8, -1)

console.log(getObjTag(person))  // log Object


Person.prototype[Symbol.toStringTag] = Person.name
console.log(getObjTag(person))  // log Person

// this method is reasonable in JS, because
console.log(getObjTag([]))  // log Array
console.log(getObjTag(new Set([])))  // log Set

Upvotes: 2

Static
Static

Reputation: 786

You could use a class to create a custom Object. However, in regards to custom data types, you can't really do that.

Here's a basic example:

class Person {
    constructor(name, age, nationality) {
        this._name = name;
        this._age = age;
        this._nationality = nationality;
    }

    info() {
        return `Hi ${this._name}, you're ${this._age} years old and your nationality is ${this._nationality}!`
    };
};

const person = new Person("John", 15, "British");
console.log(person.info())
console.log(typeof person)

You have to have the constructor function within a class; if you do not have one then JavaScript will insert an empty one.

I'm not too experienced with classes (I've just started working with them), and I'd recommend you do some further research into them - they're dead useful.

Upvotes: -2

frodo2975
frodo2975

Reputation: 11745

It sounds like you're looking for TypeScript! TypeScript is a language that compiles to JavaScript.

Here's an example from the documentation for creating a person type:

interface Person {
    firstName: string;
    lastName: string;
}

let user: Person = { firstName: "Jane", lastName: "User" };

https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html#interfaces

Upvotes: 5

Open AI - Opting Out
Open AI - Opting Out

Reputation: 1631

I thought I would point out, that the answer to "Can I create custom types?", is a definite yes. You can not however invite typeof to the party.

Here are some workarounds and alternatives to using typeof.

typeof is broken?

The typeof operator, could be considered to be a bit broken... so won't really work for "custom" types... Actually, it does not really work as you might expect with JavaScript primitives.

typeof null // "object" ?! ok..., while there are reasons why this happens, it's not intuitive.

The ideal and "safe" way to check for custom types is by defining and calling a custom toString method on your custom object.

You can read more about this on MDN

instanceof to the rescue

Instead of using typeof, you could consider using instanceof. As that will work with your "custom" class right off the bat, without needing to do any additional anything further such as implementing your own .toString method.

Here is a simple playground, demonstrating the basic idea...

class Person {}

p = new Person // An instance of Person

console.log(typeof p) // Object :(
console.log(p instanceof Person) // ture :P

// And with custom .toString method
Person.prototype.toString = function(){ return 'person' }

console.log(p.toString())        // 'person'
console.log(String(p))           // 'person'
console.log(p+"")                // 'person' <-- This is a simple coercive to string expression, employing our custom .toString method.
console.log(`${p}`)              // 'person' <-- using template literals
console.log([]+p)                // 'person' <-- coercion magic ... :p
console.log(""+{}+[":"]+p)       // "[object Object]:person"
console.log((typeof {})+' '+[p]) // "object person"

// BONUS ROUND --- we can even do "custom" JSON stringifications
Person.prototype.toJSON = function (){ return { typeof: '[object Person]'} }

console.log(JSON.stringify(p)) // "{"typeof":"[object Person]"}"

// Which works, as expected...
let agent = { agent: p }
console.log(JSON.stringify(agent)) // {"agent":{"typeof":"[object Person]"}}

Upvotes: 6

Shubham Dixit
Shubham Dixit

Reputation: 1

There are only a few return values of typeof as listed here:

Undefined         "undefined"
Null              "object" (see below)
Boolean           "boolean"
Number            "number"
BigInt            (new in ECMAScript 2020)    "bigint"
String            "string"
Symbol            (new in ECMAScript 2015)    "symbol"
Function object   (implements [[Call]] in ECMA-262 terms)    "function"
Any other object  "object"

So as per your question, you can't have your own value for typeof operator. And if you create your own object with class or function() its type will be an object.

Upvotes: 16

Pavlos Karalis
Pavlos Karalis

Reputation: 2966

The closest you can get to what you're describing is testing instanceof, or using instanceof to create your own type checking function:

class Person {
  constructor(name, age) {
    this.name = name; 
    this.age = age;
  }
}

const bill = new Person("Bill", 40);

function checkType(data){
  if(data instanceof Person) return "Person";
  return typeof data; 
}

console.log(bill instanceof Person);
console.log(checkType(bill));
console.log(checkType("bill")); 

Upvotes: 30

Related Questions