JavaScript's primitive values each have a type with the same name in lowercase: string, number, boolean, bigint and symbol, plus null and undefined, which have their own page. Inside JSDoc braces you write them exactly as in a .ts file: @type {string}, @param {number} price.
There is no separate integer or float type: number covers both, as it does at run time. For whole numbers beyond Number.MAX_SAFE_INTEGER, use bigint and the n suffix.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| Text | /** @type {string} */ | : string |
| Numbers | /** @type {number} */ | : number |
| True or false | /** @type {boolean} */ | : boolean |
| Big integers | /** @type {bigint} */ | : bigint |
| Symbols | /** @type {symbol} */ | : symbol |
Examples
/** @type {string} */
let name = "Cotton tee";
/** @type {number} */
let price = 19.5;
/** @type {boolean} */
let inStock = true;
/** @type {bigint} */
const views = 12_000_000_000n;
/** @type {symbol} */
const id = Symbol("product");
name = name.toUpperCase();
price = Math.round(price * 100) / 100;
inStock = !inStock;
export { name, price, inStock, views, id };let name: string = "Cotton tee";
let price: number = 19.5;
let inStock: boolean = true;
const views: bigint = 12_000_000_000n;
const id: symbol = Symbol("product");
name = name.toUpperCase();
price = Math.round(price * 100) / 100;
inStock = !inStock;
export { name, price, inStock, views, id };jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /**
* @param {number} price
* @param {number} quantity
*/
export function lineTotal(price, quantity) {
return price * quantity;
}
const fromForm = "19.5";
lineTotal(Number(fromForm), 2);
lineTotal(fromForm, 2);error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /** @type {string} */
const label = "Cotton tee";
/** @type {string} */
const boxed = new String("Cotton tee");error TS2322: Type 'String' is not assignable to type 'string'.
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
export { label, boxed };jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Lowercase, not capitalized
String, Number and Boolean with a capital letter are the wrapper object types, the type of new String("x"). In a .js file TypeScript reads {String}, {Number} and {Boolean} in JSDoc as the lowercase types, but new String(…) still creates a wrapper object, which is not a string: the third example assigns a new String(…) to a string and gets TS2322 with the hint "'string' is a primitive, but 'String' is a wrapper object". Write the lowercase names.
Values from forms and URLs
Input fields, query strings and localStorage give you strings. Passing one where a number is expected is the mistake the second example catches (TS2345). Convert at the boundary with Number(…) or parseInt(…, 10) and check the result with Number.isFinite before using it.
Gotchas
- A
numberparameter acceptsInfinityand the not-a-number value; the type cannot rule them out, so check withNumber.isFinitewhere it matters. - Template literals and
+with a string produce strings, soprice + ""has typestring, notnumber. - Without
strict,nullandundefinedare assignable to every primitive type.
Questions
Should I write {String} or {string} in JSDoc?
{string}. In a .js file TypeScript reads {String} as string too, but in a .ts file String is the wrapper object type, and TypeScript's own messages and the handbook use the lowercase names.
Sources
- Everyday Types: the primitives · TypeScript handbook
- JSDoc Reference: types · TypeScript handbook
- Primitive · MDN
Last reviewed 20 October 2026.