ESLint no-restricted-* 活用レシピ集:API 禁止・依存制限・危険パターン封じ込め
プロジェクトの規模が大きくなると、「このライブラリは使わないで欲しい」「この書き方は禁止したい」といったルールを明文化したくなる場面が増えてきます。チームメンバー全員に口頭で伝えても、つい忘れてしまったり、新しく参加したメンバーが知らずに使ってしまったりすることもあるでしょう。
そんなとき、ESLint の no-restricted-* 系ルールが強力な味方になってくれます。API の使用禁止、特定の依存関係の制限、危険な構文パターンの封じ込めなど、プロジェクト固有のルールを自動でチェックできるのです。
本記事では、no-restricted-imports、no-restricted-syntax、no-restricted-properties、no-restricted-globals の 4 つを中心に、実践的な活用レシピをご紹介します。
no-restricted-* ルール早見表
以下の表で、各ルールの概要と主な用途を確認できます。
| # | ルール名 | 制限対象 | 主な用途 | 設定の難易度 |
|---|---|---|---|---|
| 1 | no-restricted-imports | import 文 | 特定パッケージ・モジュールの禁止 | ★☆☆ 易しい |
| 2 | no-restricted-syntax | AST ノード(構文) | 特定の書き方・パターンの禁止 | ★★★ 高度 |
| 3 | no-restricted-properties | オブジェクトのプロパティ | 特定オブジェクトのメソッド・プロパティ禁止 | ★★☆ 中級 |
| 4 | no-restricted-globals | グローバル変数 | グローバル変数の使用禁止 | ★☆☆ 易しい |
ルール別の設定キー対応表
各ルールで使える設定キーを一覧にまとめました。
| # | ルール名 | 主要な設定キー | 説明 |
|---|---|---|---|
| 1 | no-restricted-imports | name | 禁止するパッケージ名 |
| 2 | importNames | 名前付きインポートのうち禁止する名前 | |
| 3 | message | カスタムエラーメッセージ | |
| 4 | no-restricted-syntax | selector | AST セレクター(例:ForInStatement) |
| 5 | message | カスタムエラーメッセージ | |
| 6 | no-restricted-properties | object | 対象オブジェクト名 |
| 7 | property | 禁止するプロパティ名 | |
| 8 | message | カスタムエラーメッセージ | |
| 9 | no-restricted-globals | 文字列配列 | 禁止するグローバル変数名 |
| 10 | name + message | オブジェクト形式でメッセージ付き |
背景
チーム開発における暗黙のルールの課題
チーム開発では、コーディング規約やベストプラクティスを文書化していても、すべてのメンバーが常に意識できるとは限りません。
「Lodash の _.forEach は使わずに配列メソッドを使う」「古い API は使わない」といったルールを口頭やドキュメントで伝えても、レビュー時に指摘されて初めて気づくことが多いでしょう。指摘する側も、毎回同じことを伝えるのは疲れてしまいますし、見落としが発生するリスクもあります。
プロジェクト固有の制約を自動化する必要性
プロジェクトによっては、以下のような固有の制約が存在します。
- セキュリティ上の理由で特定のライブラリを禁止
- パフォーマンスのために特定の構文を避ける
- レガシー API から新しい API への移行を促進
- モジュールの依存関係を一方向に保つアーキテクチャ制約
これらを人力でチェックし続けるのは非効率です。ESLint の no-restricted-* ルールを使えば、こうした制約をコードレベルで自動チェックできます。
次の図は、チーム開発における制約の伝達フローを示しています。
mermaidflowchart LR
rule["ルール策定"] -->|ドキュメント化| doc["README/<br/>Wikiに記載"]
doc -->|読む| dev["開発者"]
dev -->|コーディング| code["コード"]
code -->|レビュー| review["コードレビュー"]
review -->|指摘| dev
rule -.->|ESLint設定| eslint["no-restricted-*<br/>ルール"]
eslint -->|自動チェック| code
code -->|違反検出| error["ESLintエラー"]
error -->|修正| dev
図のように、ドキュメントだけに頼ると「読む → 忘れる → レビューで指摘」のサイクルが発生しますが、ESLint を使えば「書いた瞬間にエラー」として検出できます。
図で理解できる要点
- ドキュメントだけでは開発者の記憶に頼ることになる
- ESLint 設定により、コーディング時点で自動的にルール違反を検出できる
- レビュアーの負担を減らし、機械的なチェックは自動化できる
課題
特定ライブラリの使用を防ぎたい
プロジェクトによっては、以下のような理由で特定ライブラリを禁止したい場合があります。
- セキュリティホールが発見された古いバージョンのライブラリ
- バンドルサイズが大きすぎる非推奨ライブラリ
- チーム標準の代替ライブラリが存在する場合
例えば、Moment.js は非常に人気のあるライブラリでしたが、バンドルサイズの大きさやメンテナンス終了により、現在では Day.js や date-fns への移行が推奨されています。既存コードに Moment.js が混入しないようにしたいケースは多いでしょう。
危険な構文やパターンを排除したい
JavaScript には便利だが危険な構文も存在します。
for...inループはプロトタイプチェーンのプロパティまで列挙してしまうeval()は任意のコードを実行できるためセキュリティリスクが高いargumentsは関数型プログラミングの観点で非推奨with文はスコープを混乱させる
これらの構文を使わせたくない場合、no-restricted-syntax を使えば AST レベルで禁止できます。
特定のメソッドやプロパティを制限したい
オブジェクトのメソッドやプロパティ単位で制限をかけたい場合もあります。
Object.prototypeへの直接的な変更を禁止__proto__プロパティの使用を避けるArray.prototype.reduceを禁止して可読性を優先
これらは no-restricted-properties で実現できます。
次の図は、no-restricted-* ルールで対応できる課題の全体像を示しています。
mermaidflowchart TD
problem["プロジェクト固有の制約"] --> import_issue["特定ライブラリ<br/>使用禁止"]
problem --> syntax_issue["危険な構文<br/>パターン排除"]
problem --> property_issue["特定メソッド<br/>プロパティ制限"]
problem --> global_issue["グローバル変数<br/>使用制限"]
import_issue --> sol1["no-restricted-imports"]
syntax_issue --> sol2["no-restricted-syntax"]
property_issue --> sol3["no-restricted-properties"]
global_issue --> sol4["no-restricted-globals"]
sol1 --> auto["自動チェック<br/>&エラー検出"]
sol2 --> auto
sol3 --> auto
sol4 --> auto
図で理解できる要点
- プロジェクト固有の制約は、ライブラリ・構文・プロパティ・グローバル変数の 4 つに分類できる
- それぞれに対応する
no-restricted-*ルールが存在する - すべて ESLint による自動チェックで統一的に運用できる
解決策
no-restricted-imports:特定のインポートを禁止
no-restricted-imports ルールを使うと、特定のパッケージやモジュールからのインポートを禁止できます。
基本的な設定方法
ESLint 設定ファイルに以下のように記述します。
javascript// eslint.config.js (Flat Config)
export default [
{
files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
rules: {
'no-restricted-imports': [
'error',
{
// パッケージ全体を禁止
name: 'moment',
message:
'moment は非推奨です。代わりに date-fns を使用してください。',
},
],
},
},
];
上記の設定により、import moment from 'moment' と書いた瞬間に ESLint エラーが表示されます。
名前付きインポートの制限
パッケージ全体ではなく、特定の名前付きインポートのみを禁止することもできます。
javascript// 特定の名前付きインポートのみ禁止
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-imports': [
'error',
{
name: 'lodash',
importNames: ['forEach', 'each'],
message:
'lodash の forEach は使わず、Array.prototype.forEach を使ってください。',
},
],
},
},
];
この設定では import { forEach } from 'lodash' はエラーになりますが、import { map } from 'lodash' は許可されます。
パターンによる禁止
正規表現パターンを使って、複数のモジュールをまとめて禁止することもできます。
javascript// パターンマッチで禁止
export default [
{
files: ['**/*.ts'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['@internal/legacy-*'],
message: 'レガシーモジュールは使用禁止です。',
},
],
},
],
},
},
];
@internal/legacy-api、@internal/legacy-utils など、パターンにマッチするすべてのモジュールが禁止されます。
no-restricted-syntax:特定の構文パターンを禁止
no-restricted-syntax は AST(抽象構文木)のノード型を指定して、特定の構文を禁止できます。
for...in ループの禁止
for...in はプロトタイプチェーンのプロパティも列挙してしまうため、多くのプロジェクトで使用が避けられています。
javascript// for...in ループを禁止
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-syntax': [
'error',
{
selector: 'ForInStatement',
message:
'for...in は使わず、Object.keys() や for...of を使ってください。',
},
],
},
},
];
このルールにより、以下のようなコードはエラーになります。
javascript// ❌ エラー: for...in は禁止されています
for (const key in obj) {
console.log(key);
}
代わりに以下のような書き方を推奨します。
javascript// ✅ OK: Object.keys を使用
for (const key of Object.keys(obj)) {
console.log(key);
}
// ✅ OK: Object.entries を使用
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
eval の禁止
eval() は任意のコードを実行できるため、セキュリティリスクが高い機能です。
javascript// eval を禁止
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-syntax': [
'error',
{
selector: 'CallExpression[callee.name="eval"]',
message:
'eval() はセキュリティリスクがあるため使用禁止です。',
},
],
},
},
];
console.log の禁止(本番コード)
開発中は便利な console.log ですが、本番コードには残したくない場合があります。
javascript// console.log を禁止
export default [
{
files: ['src/**/*.js'],
ignores: ['**/*.test.js', '**/*.spec.js'],
rules: {
'no-restricted-syntax': [
'error',
{
selector:
'CallExpression[callee.object.name="console"][callee.property.name="log"]',
message:
'本番コードに console.log を残さないでください。',
},
],
},
},
];
テストファイルは ignores で除外しているため、テスト内では console.log を使えます。
no-restricted-properties:特定のプロパティを禁止
オブジェクトのプロパティやメソッド単位で制限をかけられます。
__proto__ の禁止
__proto__ は非標準のプロパティであり、Object.getPrototypeOf() や Object.setPrototypeOf() を使うべきです。
javascript// __proto__ を禁止
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-properties': [
'error',
{
property: '__proto__',
message:
'__proto__ は非標準です。Object.getPrototypeOf() を使ってください。',
},
],
},
},
];
Object.prototype への直接的なメソッド呼び出しを禁止
プロトタイプ汚染を避けるため、Object.prototype のメソッドは直接呼び出さず、Object 経由で呼び出すことが推奨されます。
javascript// Object.prototype.hasOwnProperty の直接呼び出しを禁止
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-properties': [
'error',
{
object: 'Object',
property: 'prototype',
message:
'Object.prototype への直接アクセスは避けてください。',
},
],
},
},
];
以下のように書き換えます。
javascript// ❌ 非推奨
obj.hasOwnProperty('key');
// ✅ 推奨
Object.prototype.hasOwnProperty.call(obj, 'key');
// ✅ より現代的
Object.hasOwn(obj, 'key');
no-restricted-globals:グローバル変数の使用を禁止
ブラウザ環境では多数のグローバル変数が存在しますが、意図せず使ってしまうとバグの原因になります。
event グローバル変数の禁止
古いブラウザでは event というグローバル変数が存在し、イベントハンドラ内で暗黙的に参照できてしまいます。
javascript// event グローバルを禁止
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-globals': [
'error',
{
name: 'event',
message:
'グローバルの event は使わず、引数で受け取ってください。',
},
],
},
},
];
以下のように明示的にイベントオブジェクトを受け取るべきです。
javascript// ❌ グローバル event を暗黙的に参照
button.addEventListener('click', function () {
console.log(event.target); // event はどこから来た?
});
// ✅ 引数で明示的に受け取る
button.addEventListener('click', function (e) {
console.log(e.target);
});
name や status などの紛らわしいグローバルを禁止
name、status、closed などは window のプロパティとして存在するため、変数名として使うと混乱を招きます。
javascript// 紛らわしいグローバルを禁止
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-globals': [
'error',
'name',
'status',
'closed',
'open',
],
},
},
];
次の図は、no-restricted-* ルールの適用範囲と、それぞれが AST のどの部分に作用するかを示しています。
mermaidflowchart TB
code["ソースコード"] --> parser["ESLint Parser"]
parser --> ast["AST<br/>(抽象構文木)"]
ast --> import_node["ImportDeclaration<br/>ノード"]
ast --> syntax_node["各種Statement<br/>ノード"]
ast --> member_node["MemberExpression<br/>ノード"]
ast --> identifier_node["Identifier<br/>ノード"]
import_node --> rule1["no-restricted-imports"]
syntax_node --> rule2["no-restricted-syntax"]
member_node --> rule3["no-restricted-properties"]
identifier_node --> rule4["no-restricted-globals"]
rule1 --> check["ルールチェック"]
rule2 --> check
rule3 --> check
rule4 --> check
check --> result["エラー or 警告"]
図で理解できる要点
- ソースコードは ESLint によって AST(抽象構文木)に変換される
no-restricted-*各ルールは、AST の異なるノードタイプに対して作用する- すべてのルールが統一されたチェック機構で動作する
具体例
レシピ 1:Lodash から Native JavaScript への移行
Lodash は便利ですが、現代の JavaScript には多くの機能が標準で備わっています。バンドルサイズ削減のため、Lodash の特定メソッドを禁止します。
設定ファイル
javascript// eslint.config.js
export default [
{
files: ['**/*.js', '**/*.ts'],
rules: {
'no-restricted-imports': [
'error',
{
name: 'lodash',
importNames: [
'forEach',
'map',
'filter',
'reduce',
'find',
'some',
'every',
],
message:
'配列メソッドはネイティブの Array.prototype を使ってください。',
},
{
name: 'lodash/forEach',
message:
'Array.prototype.forEach を使ってください。',
},
{
name: 'lodash/map',
message: 'Array.prototype.map を使ってください。',
},
],
},
},
];
エラーになるコード
javascript// ❌ Lodash のインポートはエラー
import { forEach, map } from 'lodash';
import forEach from 'lodash/forEach';
forEach([1, 2, 3], (num) => console.log(num));
推奨される書き方
javascript// ✅ ネイティブの配列メソッドを使用
[1, 2, 3].forEach((num) => console.log(num));
const doubled = [1, 2, 3].map((num) => num * 2);
レシピ 2:セキュリティリスクのある構文を完全排除
セキュリティ上問題のある構文をすべて禁止します。
設定ファイル
javascript// eslint.config.js
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-syntax': [
'error',
// eval 禁止
{
selector: 'CallExpression[callee.name="eval"]',
message:
'eval() はセキュリティリスクがあるため禁止です。',
},
// Function コンストラクタ禁止
{
selector: 'NewExpression[callee.name="Function"]',
message:
'new Function() はセキュリティリスクがあるため禁止です。',
},
// with 文禁止
{
selector: 'WithStatement',
message:
'with 文はスコープを混乱させるため禁止です。',
},
],
},
},
];
エラーになるコード
javascript// ❌ すべてエラー
eval('console.log("危険!")');
const fn = new Function('a', 'b', 'return a + b');
with (obj) {
console.log(property);
}
推奨される書き方
javascript// ✅ 安全な代替手段を使用
// eval の代わりに JSON.parse など安全な方法を使う
const data = JSON.parse('{"key": "value"}');
// Function コンストラクタの代わりに通常の関数を定義
const fn = (a, b) => a + b;
// with の代わりに明示的なプロパティアクセス
console.log(obj.property);
レシピ 3:アーキテクチャ制約の実装(レイヤー依存の禁止)
クリーンアーキテクチャやレイヤードアーキテクチャでは、依存関係の方向を制限する必要があります。
ディレクトリ構造
bashsrc/
├── domain/ # ドメイン層(最も内側)
├── application/ # アプリケーション層
├── infrastructure/ # インフラ層
└── presentation/ # プレゼンテーション層(最も外側)
設定ファイル(domain 層)
ドメイン層は他のどの層にも依存してはいけません。
javascript// eslint.config.js
export default [
{
// ドメイン層のファイルに適用
files: ['src/domain/**/*.ts'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
group: [
'**/application/**',
'**/infrastructure/**',
'**/presentation/**',
],
message:
'ドメイン層は他の層に依存してはいけません。',
},
],
},
],
},
},
];
設定ファイル(application 層)
アプリケーション層は infrastructure 層や presentation 層に依存してはいけません。
javascriptexport default [
{
files: ['src/application/**/*.ts'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
group: [
'**/infrastructure/**',
'**/presentation/**',
],
message:
'アプリケーション層は infrastructure 層や presentation 層に依存できません。',
},
],
},
],
},
},
];
エラーになるコード
typescript// ❌ src/domain/user.ts
// ドメイン層が infrastructure 層をインポート
import { UserRepository } from '../infrastructure/UserRepository';
export class User {
// ...
}
推奨される書き方
typescript// ✅ src/domain/user.ts
// ドメイン層はインターフェースのみ定義
export interface IUserRepository {
findById(id: string): Promise<User>;
}
export class User {
// ...
}
typescript// ✅ src/infrastructure/UserRepository.ts
// インフラ層がドメイン層のインターフェースを実装
import { IUserRepository, User } from '../domain/user';
export class UserRepository implements IUserRepository {
async findById(id: string): Promise<User> {
// 実装
}
}
レシピ 4:React プロジェクトでの危険なパターン禁止
React プロジェクトで避けるべきパターンを禁止します。
設定ファイル
javascript// eslint.config.js
export default [
{
files: ['**/*.jsx', '**/*.tsx'],
rules: {
'no-restricted-syntax': [
'error',
// インデックスを key に使うのを禁止
{
selector:
'JSXAttribute[name.name="key"][value.expression.type="MemberExpression"][value.expression.property.name="index"]',
message:
'key にインデックスを使わないでください。一意な ID を使用してください。',
},
],
'no-restricted-properties': [
'error',
// findDOMNode の使用を禁止
{
object: 'ReactDOM',
property: 'findDOMNode',
message:
'findDOMNode は非推奨です。ref を使ってください。',
},
// dangerouslySetInnerHTML の使用を警告
{
property: 'dangerouslySetInnerHTML',
message:
'XSS のリスクがあります。本当に必要か確認してください。',
},
],
},
},
];
エラーになるコード
jsx// ❌ インデックスを key に使用
items.map((item, index) => <div key={index}>{item}</div>);
// ❌ findDOMNode の使用
const node = ReactDOM.findDOMNode(this.refs.myComponent);
// ❌ dangerouslySetInnerHTML の使用
<div dangerouslySetInnerHTML={{ __html: userInput }} />;
推奨される書き方
jsx// ✅ 一意な ID を key に使用
items.map((item) => <div key={item.id}>{item.name}</div>);
// ✅ ref を使用
const myRef = useRef(null);
<div ref={myRef} />;
// ✅ テキストとして安全に表示
<div>{userInput}</div>;
レシピ 5:Node.js プロジェクトでの非推奨 API 禁止
Node.js では、バージョンアップに伴い非推奨になる API が存在します。
設定ファイル
javascript// eslint.config.js
export default [
{
files: ['**/*.js'],
rules: {
'no-restricted-properties': [
'error',
// Buffer コンストラクタの禁止
{
object: 'Buffer',
property: 'constructor',
message:
'new Buffer() は非推奨です。Buffer.from() や Buffer.alloc() を使ってください。',
},
],
'no-restricted-syntax': [
'error',
// require.extensions の禁止
{
selector:
'MemberExpression[object.name="require"][property.name="extensions"]',
message: 'require.extensions は非推奨です。',
},
],
},
},
];
エラーになるコード
javascript// ❌ 非推奨の Buffer コンストラクタ
const buf = new Buffer('hello');
// ❌ require.extensions の使用
require.extensions['.custom'] = function () {};
推奨される書き方
javascript// ✅ Buffer.from を使用
const buf = Buffer.from('hello', 'utf-8');
// ✅ Buffer.alloc を使用(初期化が必要な場合)
const buf = Buffer.alloc(10);
まとめ
本記事では、ESLint の no-restricted-* ルール群を使って、プロジェクト固有の制約を自動化する方法をご紹介しました。
4 つのルールの使い分け
- no-restricted-imports:特定パッケージやモジュールの使用を禁止したいとき
- no-restricted-syntax:特定の構文パターンを AST レベルで禁止したいとき
- no-restricted-properties:オブジェクトのメソッドやプロパティ単位で制限をかけたいとき
- no-restricted-globals:グローバル変数の使用を制限したいとき
導入のメリット
これらのルールを導入することで、以下のメリットが得られます。
- チームメンバー全員が同じルールを自動的に守れる
- コードレビューでの指摘回数が減り、レビュアーの負担が軽減される
- 新しいメンバーもルールを自然に学べる
- セキュリティリスクやパフォーマンス問題を未然に防げる
- アーキテクチャの依存関係を強制できる
運用のコツ
no-restricted-* ルールを運用する際は、以下の点に注意してください。
- メッセージを丁寧に書く:なぜ禁止されているのか、代わりに何を使うべきかを明記する
- 段階的に導入する:いきなりすべてを禁止せず、重要度の高いものから順に導入する
- ドキュメントと併用する:ルールの背景や理由を README や Wiki に記載する
- 定期的に見直す:プロジェクトの成長に合わせてルールを更新する
次のステップ
no-restricted-* ルールに慣れてきたら、以下にも挑戦してみてください。
- カスタム ESLint ルールの作成:プロジェクト固有のより複雑なルールを実装
- ESLint プラグインの作成:チーム内で共有できるルールセットをパッケージ化
- AST Explorer の活用:
no-restricted-syntaxで使うセレクタを視覚的に理解
プロジェクトのルールを自動化することで、チーム全体の開発効率とコード品質が向上します。ぜひ、本記事のレシピを参考に、あなたのプロジェクトに最適な制約を設定してみてください。
関連リンク
articleESLint no-restricted-* 活用レシピ集:API 禁止・依存制限・危険パターン封じ込め
articleESLint × Vitest/Playwright:テスト環境のグローバルと型を正しく設定
articleESLint パーサ比較:espree と @typescript-eslint/parser の互換性と速度
articleESLint が遅い時の処方箋:--cache/並列化/ルール絞り込みの実践
articleESLint の内部構造を覗く:Parser・Scope・Rule・Fixer の連携を図解
articleESLint 運用ダッシュボード:SARIF/Code Scanning で違反推移を可視化
articleDeno/Bun/Node のランタイムで共通動く Zod 環境のセットアップ
articleFFmpeg マッピング完全攻略:-map/-disposition/-metadata の黄金レシピ
articleYarn PnP で「モジュールが見つからない」時の解決大全:packageExtensions/patch で対処
articleESLint no-restricted-* 活用レシピ集:API 禁止・依存制限・危険パターン封じ込め
articleWeb Components のポリフィル戦略:@webcomponents 系を最小限で入れる判断基準
articleDify ワークフロー定型 30:分岐・並列・リトライ・サーキットブレーカの型
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来