The highest voted answer is 90% of the way there, but it's missing a critical detail that might affect you: it assumes your tsconfig.json "module" set to "CommonJS". If you have something else, like "module": "ES2020" or "module": "ESNext", you'll be playing whack-a-mole with import and require errors for half the day.
You don't need to change your entire project's "module" value to get past these errors, you can set a node-ts override instead. That way, the project will only be "module": "CommonJS" while node-ts runs. There are multiple ways to do this, but I do it by adding this to the bottom of my tsconfig.json file:
...
"ts-node": {
"compilerOptions": {
"module": "CommonJS"
}
}
}
Anyway, there are so many hard-learned gotcha's around setting up jasmine and typescript that I think it's worth sharing an entire working project. You can browse/clone it on github and I'll share an excerpt below:
Project Structure
.
├── .eslintrc.json
├── .prettierrc
├── LICENSE
├── package.json
├── spec/
│ └── support/
│ ├── jasmine.json
│ ├── logger.js
│ ├── slow-spec-reporter.js
│ └── type-check.js
├── src/
│ ├── index.spec.ts
│ └── index.ts
├── tsconfig.json
├── tsconfig.src.json
├── tsconfig.test.json
└── tsup.config.ts
./package.json
{
"name": "jasmine-ts-example",
"description": "A working example of a TypeScript project using the Jasmine test framework.",
"version": "0.0.1",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"license": "MIT",
"files": [
"dist"
],
"scripts": {
"compile-typescript": "tsup",
"build": "tsup",
"test": "jasmine",
"run": "npm run build && node dist/index.js"
},
"keywords": ["jasmine", "ts", "typescript", "node-ts"],
"devDependencies": {
"@types/jasmine": "^5.1.4",
"@types/node": "^20.10.6",
"@typescript-eslint/eslint-plugin": "^6.17.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.2",
"eslint-plugin-testcafe": "^0.2.1",
"jasmine": "^5.1.0",
"ts-node": "^10.9.2",
"tslib": "^2.6.2",
"tsup": "^8.0.1",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=18"
}
}
./spec/support/jasmine.json
{
"spec_dir": "",
"spec_files": ["**/*.spec.ts"],
"helpers": [
"spec/support/logger.js",
"spec/support/type-check.js"
],
"stopSpecOnExpectationFailure": false,
"random": true
}
./spec/support/logger.js
jasmine.getEnv().addReporter({
specDone: function (result) {
if (result.status !== 'excluded') {
console.log(result.fullName);
}
},
});
./spec/support/slow-spec-reporter.js
// To enable, add as a helper in your jasmine config file
const slowSpecsReporter = {
specStarted: function(result) {
this.specStartTime = Date.now()
},
specDone: function(result) {
const seconds = (Date.now() - this.specStartTime) / 1000
if (seconds > 0.5) {
console.log('WARNING - This spec took ' + seconds + ' seconds: "' + result.fullName + '"')
}
},
}
jasmine.getEnv().addReporter(slowSpecsReporter);
./spec/support/type-check.js
require('ts-node').register({
project: "tsconfig.json",
transpileOnly: true,
files: true
})
./tsconfig.json
{
"compilerOptions": {
/* Basic Options */
"target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
"module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
"lib": [
"ESNext"
] /* Specify library files to be included in the compilation. */,
"types": ["node", "jasmine"],
"allowJs": false /* Allow javascript files to be compiled. */,
"declaration": true /* Generates corresponding '.d.ts' file. */,
"declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
"sourceMap": true /* Generates corresponding '.map' file. */,
"outDir": "dist" /* Redirect output structure to the directory. */,
"importHelpers": true /* Import emit helpers from 'tslib'. */,
"downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */,
"strict": true /* Enable all strict type-checking options. */,
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
/* Module Resolution Options */
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
"baseUrl": "." /* Base directory to resolve non-absolute module names. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"references": [
{
"path": "./tsconfig.src.json"
}
],
"include": [],
"ts-node": {
"compilerOptions": {
"module": "CommonJS"
}
}
}
./tsconfig.src.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"declaration": true,
"composite": true
},
"include": ["./src/**/*.ts"],
"exclude": ["./**/*.spec.ts"]
}
./tsconfig.test.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"declaration": true,
"composite": true
},
"references": [
{
"path": "./tsconfig.src.json"
}
],
"include": ["./**/*.spec.ts", "./test/**/*.ts", "./tsup.config.ts"]
}
./src/index.spec.ts
import { myBool } from './index';
describe(`index`, () => {
it(`passes`, () => {
expect(myBool).toEqual(true);
});
});
./src/index.ts
export const myBool = false;
import Jasmine from 'path/here';. es5:var Jasmine = require('path/here');. UsebeforeEach,itandexpectinstead ofBeforeEach,ItandExpect.