TypeScriptのimport/exportは、JavaScriptの構文に「型だけを読み込む印(type)」を足したもので、typeを付けたimportはコンパイル後の.jsから消え、付けていない値のimportは残ります。 どの書き方が消えてどれが残るかを知っておくと、verbatimModuleSyntax のエラーや、実行時に「モジュールが見つからない」と止まる場面をすぐ直せます。

この記事では、書き方ごとに tsc が出力した .js を並べ、エラーは TS番号つきの全文で載せます。JavaScript 側の構文そのものや ESM と CommonJS の違いには深入りせず、型の import と拡張子に絞ります。

確認環境:Ubuntu 24.04、Node.js 22.22.2、TypeScript 7.0.2(npx tsc --version の表示は Version 7.0.2)。

import/exportの書き方の早見表

やりたいこと 書き方 出力される .js
値を名前つきで出す export const MAX_USERS = 100; そのまま残る
型を出す export type User = {...} / export interface Task {...} 消える
既定の値を出す export default function createUser() {...} そのまま残る
値を名前つきで読む import { greet } from "./user.js"; 残る
既定の値を読む import createUser from "./user.js"; 残る
まとめて読む import * as userModule from "./user.js"; 残る
型だけ読む import type { User } from "./user.js"; 行ごと消える
値と型を1行で読む import { UserStore, type Task } from "./user.js"; import { UserStore } from "./user.js";
型の既定exportを読む import type Config from "./config.js"; 行ごと消える
型をまとめて読む import type * as configTypes from "./config.js"; 行ごと消える
値を再exportする export { greet } from "./user.js"; 残る
型を再exportする export type { User } from "./user.js"; 行ごと消える
値と型を1行で再exportする export { type Task, UserStore } from "./user.js"; export { UserStore } from "./user.js";
読み込むだけ(副作用) import "./setup.js"; 残る

拡張子とエラーの対応は次のとおりです(設定は "module": "nodenext")。

書いたパス 結果 直し方
"./user.js" 通る(実体は user.ts) このまま
"./user" TS2835 .js を付ける
"./user.ts" TS5097 .js にするか rewriteRelativeImportExtensions を有効にする
"./user.ts" + rewriteRelativeImportExtensions 通る。出力は "./user.js" このまま

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「TypeScript import/exportの書き方とimport type」

サンプル一式(コピペ用)

以降の出力は、次の4ファイルから作っています。フォルダに置いて npm i -D typescript のあと npx tsc で同じ結果になります。

{ "name": "a1", "type": "module", "private": true }

上が package.json、下が tsconfig.json です。

{
  "compilerOptions": {
    "target": "es2022",
    "module": "nodenext",
    "rootDir": "src",
    "outDir": "dist",
    "strict": true
  },
  "include": ["src"]
}

src/user.ts(出す側):

export type User = { id: number; name: string };
export interface Task { title: string; done: boolean }
export const MAX_USERS = 100;
export function greet(user: User): string {
  return `こんにちは、${user.name}さん`;
}
export class UserStore {
  private users: User[] = [];
  add(user: User): void { this.users.push(user); }
  get size(): number { return this.users.length; }
}
export default function createUser(id: number, name: string): User {
  return { id, name };
}

src/setup.ts:

console.log("setup 実行");

src/main.ts(読む側):

import createUser from "./user.js";
import { greet, MAX_USERS } from "./user.js";
import type { User } from "./user.js";
import { UserStore, type Task } from "./user.js";
import * as userModule from "./user.js";
import { User as U2 } from "./user.js";
import { type Task as T2 } from "./user.js";
import "./setup.js";

const u: User = createUser(1, "佐藤");
const t: Task = { title: "資料を作る", done: false };
const u2: U2 = { id: 2, name: "鈴木" };
const t2: T2 = t;
const store = new UserStore();
store.add(u); store.add(u2);
console.log(greet(u), MAX_USERS, store.size, t2.title, Object.keys(userModule).join(","));

exportの書き方と、出力される.js

npx tsc を実行すると、user.ts からは次の dist/user.js が出力されます。

export const MAX_USERS = 100;
export function greet(user) {
    return `こんにちは、${user.name}さん`;
}
export class UserStore {
    users = [];
    add(user) { this.users.push(user); }
    get size() { return this.users.length; }
}
export default function createUser(id, name) {
    return { id, name };
}

export type と export interface の2行は跡形もなく消え、値(定数・関数・クラス)だけが残ります。 型は実行時には存在しない、というのが以降の話すべての土台です。

出すもの 実行時に存在するか .js に残るか
type / interface しない 残らない
const / function する 残る
class する(型としても値としても使える) 残る
enum する 残る

importの書き方と、消えるimport・残るimport

main.ts から出力された dist/main.js です。

import createUser from "./user.js";
import { greet, MAX_USERS } from "./user.js";
import { UserStore } from "./user.js";
import * as userModule from "./user.js";
import "./setup.js";
const u = createUser(1, "佐藤");
const t = { title: "資料を作る", done: false };
const u2 = { id: 2, name: "鈴木" };
const t2 = t;
const store = new UserStore();
store.add(u);
store.add(u2);
console.log(greet(u), MAX_USERS, store.size, t2.title, Object.keys(userModule).join(","));

元の8行の import と比べると、次のように変わっています。

元の import 出力 理由
import createUser from ... 残る 値として呼んでいる
import { greet, MAX_USERS } from ... 残る 値として使っている
import type { User } from ... 消える type 付き
import { UserStore, type Task } from ... UserStore だけ残る インライン type の部分だけ消える
import * as userModule from ... 残る 値として使っている
import { User as U2 } from ... 消える type は無いが、型としてしか使っていないと tsc が判断した
import { type Task as T2 } from ... 消える 中身がすべて type
import "./setup.js" 残る 副作用のための import

実行結果:

$ node dist/main.js
setup 実行
こんにちは、佐藤さん 100 2 資料を作る MAX_USERS,UserStore,default,greet

Object.keys(userModule) に User と Task が出てこないことからも、型が実行時に存在しないことがわかります。

6行目の import { User as U2 } のように、type を書かなくても「型としてしか使っていない import」は tsc が自動で消します。便利な一方で、「この import は残るのか消えるのか」が使い方しだいで変わります。これを書いたとおりに固定するのが、次の verbatimModuleSyntax です。

import typeとインラインtypeの使い分け

書き方 向いている場面 出力
import type { A, B } from "x" その行で読むものがすべて型 行ごと消える
import { a, type B } from "x" 同じモジュールから値と型を両方読む 値だけの import になる
import { type A, type B } from "x" 型だけだが、モジュールの読み込みは残したい verbatimModuleSyntax では import {} from "x" が残る

型の既定 export や、まとめ読みも type を付けられます。

// src/config.ts
export default interface Config { port: number; debug: boolean }
export type Mode = "dev" | "prod";
export const defaultPort = 3000;
// src/main.ts
import type Config from "./config.js";
import type * as configTypes from "./config.js";
import { defaultPort, type Mode } from "./config.js";

const mode: configTypes.Mode = "dev";
const m2: Mode = mode;
const config: Config = { port: defaultPort, debug: m2 === "dev" };
console.log(config);

export type { Config, Mode };
export { defaultPort };

出力された dist/main.js と実行結果です。

import { defaultPort } from "./config.js";
const mode = "dev";
const m2 = mode;
const config = { port: defaultPort, debug: m2 === "dev" };
console.log(config);
export { defaultPort };
$ node dist/main.js
{ port: 3000, debug: true }

import type は TypeScript 3.8 で入った構文で、公式リリースノートには「常に完全に消去され、実行時には何も残らない」と書かれています。同じページに、既定 import と名前つき import を1つの import type に並べる書き方(import type Foo, { Bar } from ...)はエラーになる、とも書かれています。その場合は2行に分けます。

再exportの書き方(index.tsにまとめる)

複数のファイルの export を1か所にまとめる index.ts の例です。

// src/index.ts
export { greet, MAX_USERS } from "./user.js";
export { default as createUser } from "./user.js";
export * as userModule from "./user.js";
export type { User } from "./user.js";
export { type Task, UserStore } from "./user.js";

出力された dist/index.js:

export { greet, MAX_USERS } from "./user.js";
export { default as createUser } from "./user.js";
export * as userModule from "./user.js";
export { UserStore } from "./user.js";

export type { User } は行ごと消え、export { type Task, UserStore } は UserStore だけが残ります。 import と同じ規則です。

verbatimModuleSyntaxを有効にするとどう変わるか

verbatimModuleSyntax は TypeScript 5.0 で入ったオプションです。公式の説明は短く、「type 修飾子のない import/export はそのまま出力し、type 修飾子のあるものは完全に落とす」というものです。tsc が「使い方を見て消すかどうか決める」のをやめ、書いたとおりに出力します。

{
  "compilerOptions": {
    "target": "es2022",
    "module": "nodenext",
    "rootDir": "src",
    "outDir": "dist",
    "strict": true,
    "verbatimModuleSyntax": true
  },
  "include": ["src"]
}

先ほどの main.ts をこの設定でコンパイルすると、6行目でエラーになります。

$ npx tsc
src/main.ts(6,10): error TS1484: 'User' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.

npx tsc --locale ja での表示:

src/main.ts(6,10): error TS1484: 'User' は型であり、'verbatimModuleSyntax' が有効であるときは、型のみのインポートを使用してインポートされる必要があります。

エラーがあっても .js は出力されます。そのときの main.js の import 部分はこうなりました。

import createUser from "./user.js";
import { greet, MAX_USERS } from "./user.js";
import { UserStore } from "./user.js";
import * as userModule from "./user.js";
import { User as U2 } from "./user.js";
import {} from "./user.js";
import "./setup.js";

違いは2点です。

元の行 オプションなし verbatimModuleSyntax
import { User as U2 } from ... 消える そのまま残る(TS1484)
import { type Task as T2 } from ... 消える import {} from "./user.js"; が残る

型である User を値として読み込む行がそのまま残るので、この .js を Node.js で動かすと読み込みの段階で止まります(パスは一般的な名前に置き換えています)。

$ node dist/main.js
file:///home/taro/app/dist/main.js:5
import { User as U2 } from "./user.js";
         ^^^^
SyntaxError: The requested module './user.js' does not provide an export named 'User'

TS1484 は、この実行時エラーをコンパイルの段階で知らせてくれるものです。直し方は type を付けるだけです。

// 直す前
import { User as U2 } from "./user.js";
// 直した後(どちらでもよい)
import type { User as U2 } from "./user.js";
import { type User as U2 } from "./user.js";

なお、import { type Task as T2 } が import {} from "./user.js" として残るのは公式ドキュメントにも例がある動作で、「モジュールの読み込み(副作用)は残す」という意味になります。読み込み自体も不要なら import type { Task as T2 } と書きます。

verbatimModuleSyntaxで出るエラーを3つまとめて再現する

// src/main.ts
import { User, greet } from "./user.js";
import type { UserStore } from "./user.js";
export { Task } from "./user.js";

const u: User = { id: 1, name: "佐藤" };
console.log(greet(u));
const store = new UserStore();
$ npx tsc
src/main.ts(1,10): error TS1484: 'User' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
src/main.ts(3,10): error TS1205: Re-exporting a type when 'verbatimModuleSyntax' is enabled requires using 'export type'.
src/main.ts(7,19): error TS1361: 'UserStore' cannot be used as a value because it was imported using 'import type'.
$ npx tsc --locale ja
src/main.ts(1,10): error TS1484: 'User' は型であり、'verbatimModuleSyntax' が有効であるときは、型のみのインポートを使用してインポートされる必要があります。
src/main.ts(3,10): error TS1205: 'verbatimModuleSyntax' が有効な場合に型を再エクスポートするには、'export type' を使用する必要があります。
src/main.ts(7,19): error TS1361: 'import type' を使用してインポートされたため、'UserStore' は値として使用できません。
TS番号 原因 直し方
TS1484 型を type なしで import した import { type User, greet } または import type { User }
TS1205 型を type なしで再export した export type { Task } from "./user.js";
TS1361 import type したクラスを new した クラスを値として使うなら type を外す
TS1295 CommonJS 扱いのファイルに import/export を書いた 下の節を参照

直した後の main.ts です。エラーなしでコンパイルできます。

import { type User, greet } from "./user.js";
import { UserStore } from "./user.js";
export type { Task } from "./user.js";

const u: User = { id: 1, name: "佐藤" };
console.log(greet(u));
const store = new UserStore();

TS1205 は "isolatedModules": true だけを付けた場合にも出ます。メッセージのオプション名だけが変わります。

src/main.ts(1,10): error TS1205: Re-exporting a type when 'isolatedModules' is enabled requires using 'export type'.

CommonJS扱いのファイルではTS1295になる

package.json を "type": "commonjs" にして同じ設定でコンパイルすると、import と export の両方が指摘されます。

$ npx tsc
src/main.ts(1,10): error TS1295: ECMAScript imports and exports cannot be written in a CommonJS file under 'verbatimModuleSyntax'. Adjust the 'type' field in the nearest 'package.json' to make this file an ECMAScript module, or adjust your 'verbatimModuleSyntax', 'module', and 'moduleResolution' settings in TypeScript.
src/user.ts(3,1): error TS1287: A top-level 'export' modifier cannot be used on value declarations in a CommonJS module when 'verbatimModuleSyntax' is enabled.
…(TS1287 が export の数だけ続く)…

verbatimModuleSyntax は「書いたとおりに出力する」オプションなので、import 文を require に書き換える出力とは両立しません。package.json を "type": "module" にするのがいちばん簡単な直し方です。公式ドキュメントには、CommonJS のまま使う場合の書き方として import foo = require("foo"); と export = {...}; が挙げられています。

拡張子の書き方:なぜ.tsなのに.jsと書くのか

"module": "nodenext" では、相対パスの import に拡張子が必要です。そして書くのは 出力後のファイル名である .js です。tsc は import のパスを書き換えずに出力するため、「実行時に Node.js が探すファイル名」をそのまま書く、という考え方です。型チェックのときは、./user.js と書かれていれば tsc が隣の user.ts を見つけてくれます。

拡張子なしはTS2835

// src/main.ts
import { greet } from "./user";
import { MAX_USERS } from "./usre.js";
console.log(greet({ id: 1, name: "佐藤" }), MAX_USERS);
$ npx tsc
src/main.ts(1,23): error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './user.js'?
src/main.ts(2,27): error TS2307: Cannot find module './usre.js' or its corresponding type declarations.
$ npx tsc --locale ja
src/main.ts(1,23): error TS2835: 相対インポート パスでは、'--moduleResolution' が 'node16' または 'nodenext' である場合、ECMAScript インポートに明示的なファイル拡張子が必要です。'./user.js' を意図していましたか?
src/main.ts(2,27): error TS2307: モジュール './usre.js' またはそれに対応する型宣言が見つかりません。

TS2835 は「./user.js のことですか?」と候補まで出してくれます。2行目はファイル名のつづり間違い(usre)で、こちらは TS2307 になります。拡張子が無いだけなら TS2835、ファイル自体が見つからないなら TS2307 と読み分けられます。

同じファイルを、バンドラー向けの設定(--module preserve --moduleResolution bundler)でチェックすると、拡張子なしの1行目は通り、TS2307 だけが残りました。

$ npx tsc --noEmit --module preserve --moduleResolution bundler
src/main.ts(2,27): error TS2307: Cannot find module './usre.js' or its corresponding type declarations.
設定 "./user" "./user.js" 向いている使い方
"module": "nodenext" TS2835 通る tsc の出力を Node.js でそのまま動かす
"moduleResolution": "bundler" 通る 通る Vite などのバンドラーがパスを解決する

.tsと書くとTS5097

import { greet } from "./user.ts";
console.log(greet({ id: 1, name: "佐藤" }));
$ npx tsc
src/main.ts(1,23): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.

メッセージに従って allowImportingTsExtensions だけを足すと、今度は設定の組み合わせを指摘されます。

$ npx tsc --allowImportingTsExtensions
tsconfig.json(1,3): error TS5096: Option 'allowImportingTsExtensions' can only be used when one of 'noEmit', 'emitDeclarationOnly', or 'rewriteRelativeImportExtensions' is set.

--allowImportingTsExtensions --noEmit ならエラーなしで終わりました。つまり .ts 拡張子の import は「tsc で .js を出力しない(型チェックだけに使う)」か「出力時に書き換える」かのどちらかとセットです。

rewriteRelativeImportExtensionsで.ts拡張子のまま書く

rewriteRelativeImportExtensions は TypeScript 5.7 で入ったオプションで、相対パスの .ts .tsx .mts .cts を、出力時に対応する JavaScript の拡張子へ書き換えます。

{
  "compilerOptions": {
    "target": "es2022",
    "module": "nodenext",
    "rootDir": "src",
    "outDir": "dist",
    "strict": true,
    "rewriteRelativeImportExtensions": true,
    "verbatimModuleSyntax": true
  },
  "include": ["src"]
}
// src/main.ts
import { greet } from "./user.ts";
import type { User } from "./user.ts";

const u: User = { id: 1, name: "佐藤" };
console.log(greet(u));

const name = "user";
const mod = await import("./" + name + ".ts");
console.log(Object.keys(mod).join(","));
const mod2 = await import("./user.ts");
console.log(mod2.MAX_USERS);

エラーなしでコンパイルでき、dist/main.js は次のようになりました。

var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
    if (typeof path === "string" && /^\.\.?\//.test(path)) {
        return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
            return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
        });
    }
    return path;
};
import { greet } from "./user.js";
const u = { id: 1, name: "佐藤" };
console.log(greet(u));
const name = "user";
const mod = await import(__rewriteRelativeImportExtension("./" + name + ".ts"));
console.log(Object.keys(mod).join(","));
const mod2 = await import("./user.js");
console.log(mod2.MAX_USERS);
  • 静的な import の "./user.ts" は "./user.js" に書き換わる
  • 文字列を組み立てる動的 import には、実行時にパスを書き換える補助関数が差し込まれる
$ node dist/main.js
こんにちは、佐藤さん
MAX_USERS,UserStore,default,greet
100

Node.js 22.22.2 は .ts ファイルを直接実行できるため、同じソースをコンパイルせずに動かすこともできました。

$ node src/main.ts
こんにちは、佐藤さん
MAX_USERS,UserStore,default,greet
100

「開発中は node で .ts を直接動かし、配布用には tsc で .js を出力する」という両立ができるのが、このオプションの役割です。verbatimModuleSyntax を一緒に付けているのは、Node.js が .ts を直接動かすときは型の部分を取り除くだけで、「型としてしか使っていない import」を判断して消してはくれないためです。type を書いておけば、どちらの動かし方でも同じ結果になります。

公式リリースノートによると、書き換えの対象になるのは「./ か ../ で始まる」「TypeScript の拡張子で終わる」「宣言ファイル(.d.ts)ではない」をすべて満たすパスだけです。次のものは書き換わりません。

書き換わらないパス 例
拡張子のない相対パス "./foo"
パッケージ名から始まるパス "some-package/file.ts"
tsconfig の paths を使ったパス "@/utilities.ts"
package.json の imports を使ったパス "#root/utilities.ts"

エラーから直し方を引く早見表

TS番号 メッセージの要点 原因 直し方
TS1484 is a type and must be imported using a type-only import verbatimModuleSyntax で型を type なし import type を付ける
TS1205 Re-exporting a type ... requires using 'export type' 型を type なしで再export export type { ... } from
TS1361 cannot be used as a value because it was imported using 'import type' type 付きで読んだものを値として使った type を外す
TS1295 ECMAScript imports and exports cannot be written in a CommonJS file CommonJS 扱いのファイル+verbatimModuleSyntax package.json を "type": "module" に
TS2835 Relative import paths need explicit file extensions nodenext で拡張子なし .js を付ける
TS2307 Cannot find module ファイル名・パスの間違い つづりとパスを確かめる
TS5097 An import path can only end with a '.ts' extension when ... .ts 拡張子で import .js にするか rewriteRelativeImportExtensions
TS5096 'allowImportingTsExtensions' can only be used when ... 出力ありで allowImportingTsExtensions noEmit か rewriteRelativeImportExtensions と組み合わせる

設定の選び方

使い方 おすすめの設定 import の書き方
tsc の出力を Node.js で動かす "module": "nodenext" + "verbatimModuleSyntax": true "./user.js"、型には type
Node.js で .ts を直接動かし、配布時は tsc で出力 上記+ "rewriteRelativeImportExtensions": true "./user.ts"、型には type
バンドラーに任せ、tsc は型チェックだけ "moduleResolution": "bundler" + "noEmit": true + "verbatimModuleSyntax": true 拡張子は省略可、型には type

どの使い方でも verbatimModuleSyntax を有効にして「型には type」を習慣にしておくと、tsc 以外のツール(1ファイルずつ変換するツールや、Node.js の直接実行)に持っていっても同じ結果になります。

よくある質問

Q. import type と、普通の import はどちらを使えばよいですか? A. 型(type・interface)だけを読むなら import type、値と型を同じ行で読むならインラインの type を使います。verbatimModuleSyntax を有効にしておけば、付け忘れを TS1484 が教えてくれます。

Q. クラスは import type で読めますか? A. 型注釈に使うだけなら読めます。new すると TS1361 になるので、値として使う場合は type を外します。公式リリースノートには、継承(extends)に使う場合も同じくエラーになると書かれています。

Q. なぜ .ts ファイルを import するのに .js と書くのですか? A. tsc は import のパスを書き換えずに出力するため、実行時に存在するファイル名(.js)を書きます。.ts と書きたい場合は rewriteRelativeImportExtensions を有効にすると、出力時に .js へ書き換わります。

Q. import {} from "./user.js" という行が出力されました。 A. verbatimModuleSyntax で import { type A } のように中身がすべてインライン type の import を書くと、この形で残ります。モジュールの読み込み自体が不要なら import type { A } に書き換えると行ごと消えます。

まとめ

  • 型(type・interface)は実行時に存在しないので、export しても .js には残らない
  • import type と export type は行ごと消え、インラインの type はその名前だけが消える
  • オプションなしの tsc は、type が無くても型としてしか使っていない import を自動で消す
  • verbatimModuleSyntax は「書いたとおりに出力」に固定する。型に type が無いと TS1484、再export は TS1205
  • "module": "nodenext" では相対パスに .js を付ける。無いと TS2835、.ts と書くと TS5097
  • rewriteRelativeImportExtensions を使うと .ts 拡張子のまま書け、出力時に .js へ書き換わる
  • CommonJS 扱いのファイルで verbatimModuleSyntax を使うと TS1295。package.json を "type": "module" にする

参考・出典

  • TypeScript 公式 TSConfig リファレンス「verbatimModuleSyntax」 https://www.typescriptlang.org/tsconfig/verbatimModuleSyntax.html
  • TypeScript 公式 TSConfig リファレンス「rewriteRelativeImportExtensions」 https://www.typescriptlang.org/tsconfig/rewriteRelativeImportExtensions.html
  • TypeScript 5.7 リリースノート(Path Rewriting for Relative Paths) https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html
  • TypeScript 3.8 リリースノート(Type-Only Imports and Exports) https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「TypeScript import/exportの書き方とimport type」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?