miso_soup3 Blog

主に ASP.NET 関連について書いています。

TypeScript の readonly な型と仕様

TypeScript で、readonly な仕組みとしてどのような型や仕様があるのか気になり調べました。見つけた範囲で書きます。

試したコードは gist にあります: TypeScript readonly

目次:

※以降のコードには、readonly なのでこのコードは書けない、ということを示すため、コンパイルエラーとなる記述が含まれます。同じ行のコメントに「// Error:」とかいてあるものがコンパイルエラーとなる行です。

Read-only properties

readonly 修飾子は TypeScript 2.0 でリリースされたようです(参照

interface Foo {
    readonly bar: number;
    readonly bas: number;
}

const foo: Foo = { bar: 1, bas: 2 };
foo.bar = 11; // Error: Cannot assign to 'bar' because it is a read-only property
class Person {
    constructor(readonly name: string) {
    }

    write() {
        this.name = 'new name'; // Error: [ts] Cannot assign to 'name' because it is a read-only property. [2540]
    }
}
const value: { readonly name: string } = { name: 'name' };
value.name = 'new name'; // Error: [ts] Cannot assign to 'name' because it is a read-only property. [2540]

readonly に限った話ではないですが、型を崩せば値を変更できてしまいます。

(foo as { bar: number }).bar = 999;
(foo as any).bar = 999;
Read-only index signatures
const dic: { readonly [key: number]: number } = {
    0: 100,
    1: 101,
    2: 102,
};
dic[103] = 103;// Error Index signature in type '{ readonly [key: number]: number; }' only permits reading.

Readonly<T>

Readonly<T> は、2.1 から使えます。参考: TypeScript 2.1 · TypeScript

interface Category {
    name: string;
    [key: number]: number;
}

let category1: Readonly<Category> = { name: 'category1' };
category1 = { name: 'new cateogry name' }; // ok
category1.name = 'new name'; // Error: [ts] Cannot assign to 'name' because it is a read-only property. [2540]
category1[100] = 100; // Error: [ts] Index signature in type 'Readonly<Category>' only permits reading. [2542]
const state1: Readonly<{ name: string }> = { name: 'name' };
state1.name = 'new name';// Error: Cannot assign to 'name' because it is a read-only property.

sample:

function read<T extends Category>(value: Readonly<T>) {
    value.name = 'new name';// Error: Cannot assign to 'name' because it is a read-only property.
}

以下の記述は 2.8 からです。参考: Improved control over mapped type modifiers

type ReadonlyCategory = { +readonly [P in keyof Category]: Category[P] };
const category2: ReadonlyCategory = category1;
category2.name = 'new name'; // Error: [ts] Cannot assign to 'name' because it is a read-only property. [2540]
category2[100] = 100; // Error: [ts] Index signature in type 'Readonly<Category>' only permits reading. [2542]

type MutableCategory = { -readonly [P in keyof ReadonlyCategory]: ReadonlyCategory[P] };
const category3: MutableCategory = category2;
category3.name = 'new name';// ok
category3[100] = 100;// ok

ReadonlyArray<T>

ReadonlyArray<T>、ReadonlyMap<T>、ReadonlySet<T> は、readonly 修飾子と同じタイミングの 2.0 から使えます。

const numbers = [1, 2, 3];
numbers.push(4);

const numbers2: ReadonlyArray<number> = numbers;
numbers2.push(5);// Error: [ts] Property 'push' does not exist on type 'ReadonlyArray<number>'. [2339]
numbers2[0] = 4;// Error: [ts] Index signature in type 'ReadonlyArray<number>' only permits reading. [2542]

ReadonlyMap<T>

const map = new Map<string, string>();
map.set("key1", "value1");
const readonlyMap: ReadonlyMap<string, string> = map;
readonlyMap.set("key1", "value1");// Error: Property 'set' does not exist on type 'ReadonlyMap<string, string>'.

ReadonlySet<T>

const set = new Set<string>();
set.add('value');
const readonlySet: ReadonlySet<string> = set;
readonlySet.add('value;');// Error: [ts] Property 'add' does not exist on type 'ReadonlySet<string>'.

Bitbucket Dashboard を自分用に見やすくする Chrome の拡張機能を作りました

f:id:miso_soup3:20190202162639j:plain

Bitbucket Dashboard Helpers - Chrome ウェブストア

Bitbucket の Dashboard が見辛くてしょうがないので Chrome 拡張機能を作りました。実体はただのペラ一枚のScriptです: miso.bitbucketboard/dashboard.js at master · hhyyg/miso.bitbucketboard。一応既存の拡張を検索してみたのですが、Bitbucket の拡張機能はたくさんあり、良さそうなものを見つけられませんでした。

今回初めてChrome 拡張機能を作り、開発の敷居が低くなりました。これからも何か見辛いのがあれば、CSS 上書きや Chrome 拡張機能で解決しよう、という気持ちになりました。

ところで謎なのですが、Bitbucket の HTML の class の値はランダムっぽい値で、数日毎(?)に変わるようでした。↓こんな感じです。

f:id:miso_soup3:20190202163425p:plain

これは、なんのためにこのようになっているのでしょうか?スクレイピング対策でしょうか? こういうフレームワークがあるのでしょうか? また、どのようなロジックで値を出力しているのでしょうか? 気になります…。