TypeScriptは静的型付け言語なのかという話

この辺の話。

(中略)

これ、私はtestを呼び出す際にanyからの暗黙のキャストが入っているという理解なのですよね。 こういうイメージ。

const test = (f: string) => console.log(typeof f);
const foo: any = [1];
test(foo as string);

こういう互換性のないキャストがエラーもなくできてしまうという意味で弱い型付けなのではないかと。

最後書いているように、若干極論ではありますが、C/C++でポインタだとキャストしてしまえばなんでも渡せてしまうよね、という話はありますしね。

#include <iostream>
#include <typeinfo>
#include <cstdlib>
#include <cxxabi.h>

static char* buffer = 0;
static size_t bufferSize = 0;

static const std::string getTypeName(const std::type_info& type)
{
    int status;
    char* name = abi::__cxa_demangle(type.name(), buffer, &bufferSize, &status);
    if (name && status == 0) {
        std::string s(name);
        buffer = name;

        return s;
    }

    return "";
}

__attribute__((destructor))
static void cleanup()
{
    if (buffer) {
        free(buffer);
    }
}

class Foo
{
public:
  virtual void method() {}
};

class Bar : public Foo {};

class Baz
{
public:
  virtual void method() {}
};

void test(const Foo* p)
{
    std::cout << getTypeName(typeid(*p)) << std::endl;
}


int main()
{
    Foo foo;
    Bar bar;
    Baz baz;

    test(&foo); // Foo
    test(&bar); // Bar
    test(reinterpret_cast<Foo *>(&baz)); // Baz

    return 0;
}

まぁ、暗黙的にanyからキャストされてしまうTypeScriptと明示的なキャストが必要なC/C++を同列に語るのも乱暴といえば乱暴ではあります。 ただ、いずれにしても他の静的型付け言語で備えているような機能を一部備えていないとしても、TypeScriptの型システムのほとんどは静的なチェックなので、静的型付けと呼ぶしかないような気がします。 C++のdynamic_castやJavaでのダウンキャストは動的な型チェックでもあったりするので、そもそも無理に分類する必要もないんじゃないかという話もありますけど。