Yuki's Tech Blog

仕事で得た知見や勉強した技術を書きます。

TSとRubyの構文をざっくり比べてみた

目次

概要

Rubyを半年くらい触っていないので、最近使っているTSと比較したいなと思い記事を書きました。Rubyのお作法を忘れてしまったので、この記事を通して思い出せればいいなと思っています。

インデント

TSではインデントは2つ、Rubyは2つです。

セミコロン

TSでは基本的にはセミコロンを書きます(プロジェクトによって書かなかったりします)。Rubyの場合、セミコロンは書かなくて大丈夫です。

文字列の結合

TS

加算演算子でもできますが、JSのテンプレートリテラルを使うと簡単にできます。

const firstName = "Ken";
const lastName = "Tanaka";
const fullName = `${lastName} ${firstName}`;

console.log(fullName); // => Tanaka Ken

Ruby

式展開を使います。加算演算子で足すこともできます。一般的には式展開を使います。

first_name = "Ken";
last_name = "Tanaka";
full_name = "#{last_name} #{first_name}";

puts full_name # => Tanaka Ken

2つのコードを比較

  • テンプレートリテラルも式展開も似ていますが、テンプレートリテラルではバッククォートを使用するのに対して、Rubyではダブルクォーテーションを使用しています。また、TSでは$を使うのに対して、Rubyでは#を使用しています。
  • Rubyでは括弧を書きません。

変数

TS

let lastName: string
lastName = "Tanaka"

console.log(lastName); // => Tanaka

Ruby

last_name = "Tanaka"

puts last_name; # => Tanaka

last_name = 1

puts last_name # => 1

2つのコードを比較

  • TSでは変数を宣言するのにletを使用します。また、変数だけを先に宣言して後から代入するのも可能です。TSの変数名はローワーキャメルケースで書きます。
  • Rubyで変数を宣言する場合、何かしらの値を代入する必要があります。変数だけ先に宣言するのはできません。Rubyの変数名とメソッド名はスネークケースで書きます。
  • Rubyの変数は特定の型に制限されないので、同じ変数に自由に型の違う値を代入できます。しかし、推奨されていません。

定数

TS

const firstName = "Ken";

console.log(firstName); // => Ken

Ruby

FIRST_NAME = "Ken"

puts FIRST_NAME # => Ken

FIRST_NAME = "Mike" # => Main.rb:5: warning: already initialized constant FIRST_NAME

2つのコードを比較

  • TSのconstで宣言する定数は変数なので、変数名は基本的にはキャメルケースで定義します。しかし、APIのエンドポイントなど、本当の意味で定数として定義したい場合、constで変数宣言して、変数名をアッパースネークケースにします(CREATE_USER_URL等)。
  • Rubyの場合、アッパースネークケースで定数を定義します。

加算代入演算子、インクリメント演算子

TS

let count = 0;

count++;
count += 1;
console.log(count); // => 2

Ruby

count = 0

count += 2
puts count # => 2

2つのコードを比較

  • Rubyにはインクリメント演算子がないので、加算代入演算子を基本的には使っていきます。

出力

TS

const firstName = "Ken";
console.log(firstName);  // => "Ken"

Ruby

first_name = "Ken"
puts first_name # => Ken
p first_name # => "Ken"

2つのコードを比較

  • TSではconsole.logを使用します。
  • Rubyではputsまたはpを使用します。putsメソッドが一般ユーザー向けで、pメソッドが開発者向けです。

if文

TS

let count = 0;

if (count === 0) {
  count++;
} else if (count === 1) {
  count += 2;
} else {
  count = 0;
}

console.log(count); // => 1

Ruby

count = 0;

if count == 0
  count += 1
elsif count == 1
  count += 2
else
  count = 0;
end

puts count # => 1

2つのコードを比較

  • TSのif文では括弧や波括弧を付けますが、Rubyのif文では付けません。その代わりRubyのif文にはendをつけます。
  • Rubyの場合、==を使用します。TSの場合はイコール3つなので気をつけましょう。

TS

// let isOk: boolean
// let count: number
// let firstName: string
// 上の変数はそれぞれ別に定義しなくても、まとめて定義できます
let isOk: boolean, count: number, firstName: string;

isOk = true;
count = 1;
firstName = "Ken";

console.log(isOk, count, firstName) // => true 1 "Ken"

Ruby

  • Rubyは実行時に型が決まるので、自分で型を書いたりしません。

右辺と左辺が等しいか比較する

TS

let firstName = "Ken";

console.log(firstName === "Ken"); // => true
console.log(firstName === "Tarou"); // => false

console.log(firstName !== "Ken"); // => false
console.log(firstName !== "Tarou"); // => true

Ruby

first_name = "Ken"

puts first_name == "Ken" # => true
puts first_name == "Tarou" # => false

puts first_name != "Ken" # => false
puts first_name != "Tarou" # => true

2つのコードを比較

  • TSでは===!==を使用します。
  • Rubyでは==!=を使用します。

論理演算子(論理和演算子論理積演算子)

TS

let initialCount = 0;
let count = 1;
let isOne = true;
let isTwo = false;

// どちらもtruthyな値の場合
console.log(count || isOne); // => 1
console.log(isOne || count); // => true
console.log(isOne && count); // => 1
console.log(count && isOne); // => true

// 片方がfalsyな値の場合
console.log(count || isTwo); // => 1
console.log(isTwo || count); // => 1
console.log(isTwo && count); // => false
console.log(count && isTwo); // => false

// どちらもfalsyな値の場合
console.log(initialCount || isTwo); // => false
console.log(isTwo || initialCount); // => 0
console.log(isTwo && initialCount); // => false
console.log(initialCount && isTwo); // => 0

Ruby

initial_count = false
count = 1
is_one = true
is_two = false

# どちらもtruthyな値の場合
puts count || is_one # => 1
puts is_one || count # => true
puts is_one && count # => 1
puts count && is_one # => true

# 片方がfalsyな値の場合
puts count || is_two # => 1
puts is_two || count # => 1
puts is_two && count # => false
puts count && is_two # => false

# どちらもfalsyな値の場合
puts initial_count || is_two # => false
puts is_two || initial_count # => false
puts is_two && initial_count # => false
puts initial_count && is_two # => false

2つのコードを比較

  • TSとRubyではFalsyな値が違います。以下の表にまとめます。
言語 falsyな値
TypeScript false, 0, -0, 0n, "", '', ``, null, undefined, NaN, document.all
Ruby false, nil
  • 論理演算子については以下の記事で解説したので、省略させていただきます。

TSとGoの構文をざっくり比べてみた - Yuki's Tech Blog

switch文

TS

let n = 2;

switch (n) {
  case 1:
    console.log("大吉です")
    break;
  case 2:
  case 3:
    console.log("吉です")
    break;
  default:
    console.log("凶です")
}

Ruby

n = 2;

case n
when 1
  puts "大吉です"
when 2, 3
  puts "吉です"
else
  puts "凶です"
end

2つのコードを比較

  • TSではSwitch文、Rubyではcase文を用います。
  • switch文ではbreak文を書くのに対して、Rubyではbreak文を書く必要はありません。
  • RubyはGoと同じでカンマで区切ることで、比較したい値を複数書くことができます。

import文

TS

import React from "react";
import { useForm } from "react-hook-form";

Ruby

# require './sample.rb'の拡張子の.rbは省略できます
require './sample'

2つのコードを比較

  • Rubyではimport文の代わりにreuireを用います。
  • requireは、組み込みライブラリでない標準ライブラリやgemを利用する場合や、自分で作成したRubyプログラムを読み込む場合に使用します。

for文

TS

for (let i = 0; i < 3; i++) {
  console.log("hoge");
}

// TSだとfor文よりforEachを使う印象がある
[...Array(3).keys()].forEach((item) => {
  console.log("hoge")
})

Ruby

nums = [1, 2, 3]

nums.each do |num|
  puts num
end

2つのコードを比較

Rubyではfor文ではなくeachメソッドを用います。

関数

TS

// 方法1: functionキーワードを使う
// function setUser (name: string, age: number) {
//   return {
//     name,
//     age,
//   }
// }

// 方法2: 関数式を使う。関数式をfunctionキーワードで書く(あまり使わない)
// 関数式では名前を省略できる。名前を持たない関数を無名関数と呼ぶ。
// const setUser = function(name: string, age: number) {
//   return {
//     name,
//     age,
//   }
// };

// 方法3: 関数式を使う。関数式をアロー関数で書く(よく使う)
// アロー関数を用いると、関数式の関数に名前をつけることはできません(常に無名関数)。
// 戻り値の型は省略できます。
const setUser = (name: string, age: number): {name: string, age: number}  => {
  return {
    name,
    age,
  }
};

const user = setUser("Ken", 25);
console.log(user);

Ruby

# {name:, age:}は、{name: name, age: age}の省略記法
def set_user(name, age)
  {name:, age:}
end

user = set_user("Ken", 25);
puts user; # => {:name=>"Ken", :age=>25}

2つのコードを比較

  • Rubyでは関数の代わりにメソッドというものがあります。
  • メソッド名は変数名と同じでスネークケースで書きます。
  • メソッドの戻り値は最後に評価された式なので、return文を書く必要はありません。
  • 引数のないメソッドの場合、括弧を省略することができます。引数があるメソッドの場合、括弧をつけましょう。

オブジェクト・ハッシュ

TS

let user = {name: 'yuki', age: 25};

console.log(user)
// => {
//      "name": "yuki",
//      "age": 25
//    } 

console.log(user.name); // => "yuki"

user.name = 'hoge';

console.log(user.name) // => "hoge"

Ruby

# ハッシュのキーにシンボルを指定した場合、ハッシュロケットを省略して、以下のようにハッシュを書くことができます。
user = {name: 'yuki', age: 25};

p user
# => {
#      "name": "yuki",
#      "age": 25
#    } 

# キーがシンボルなので、シンボルを指定してキーに対応したバリューを取得する
puts user[:name] # => "yuki"

user[:name] = 'hoge';

puts user[:name] # => "hoge"

2つのコードを比較

  • RubyでTSのオブジェクトに値するものは、ハッシュです。
  • ハッシュのキーにはシンボルを指定するのが一般的です。シンボルとは、文字列のような見た目をした整数です。内部的には整数なので、文字列を使用するような処理ではシンボルを使ったほうが高速に処理できます。
  • TSのオブジェクトでは.の後ろにプロパティ名を書くことでバリューを取得できます。Rubyのハッシュでは、ハッシュの後ろに[キー]を書くことでキーに対応したバリューを取得できます。代入するときも同じです。

感想

他にもクラスとかまだまだ比較できてない部分もあるので、見つけ次第、追記していきます!

参考記事

Rubyの===演算子についてまとめてみた|TechRacho by BPS株式会社

Rubyのインクリメント速度のバージョンごとの比較 - Qiita

変数と定数 (Ruby 3.1 リファレンスマニュアル)

Ruby入門 - 演算子 - とほほのWWW入門

Ruby の型チェッカーの比較 | Wantedly Engineer Blog

Falsy について

Falsy - MDN Web Docs Glossary&colon; Definitions of Web-related terms | MDN

Ruby 3.1: ES6風のハッシュリテラル省略記法が追加(翻訳)|TechRacho by BPS株式会社

Rubyの文字列とシンボルの違いをキッチリ説明できる人になりたい - Qiita