77548


既存のサードパーティ api に対する型付けを行っていると、例えば特殊な形式の文字列がサーバーから return
される場合があります。例えば、json文字列のような。

[code]

    {"foo":"bar"}
    
[/code]

このようなフィールドに対しては、 api の戻り値の型として、単純な`string`を定義するのではなく、例えば`json_string`
のような型を定義して、これは以下の用途で利用可能であってほしいと思っています。

  1. `string` が代入可能な所には代入できる
  2. `string` が持っているメソッド・プロパティを呼び出せる
  3. ただの `string` を `json_string` に対しては代入できない

これができると何が嬉しいかというと、その特定の形式の文字列を前提とした関数を定義する際に、間違ったフィールド・値をそこに代入してしまうのを防ぐことができます。

# 質問

上記のように、 string を特殊化したような型を定義したいのですが、これは可能でしょうか?


CC BY-SA 4.0
2021-04-19T05:58:50.863
75374
2021-06-14T08:46:37.780
754
question
typescript
typescript で、 string を特殊化したい


これが「できた」/「可能」と言えるか分かりませんが  
[Playground](https://www.typescriptlang.org/ja/play) で試すと, `let o: object =
'hello'` だとエラーになり, `let o: object = 'hello' as Object` で通ります。  
このあたりの動作がよくわからないので, 適当な部分が含まれています

[code]

    type json_string = string & {
      toObj: (s:json_string) => any
    }
    
    let o: object = 'hello' as Object
    let s: string = 'abc'
    let js: json_string = 'abc' as json_string  // Type Assertionなしだとエラー
    s = js
    o = js
    js = s // エラー, Type Assertion付けると通る
    
    function fn(arg: string): string {
      return arg
    }
    
    // どちらも通る
    fn(s)
    fn(js)
    
[/code]


CC BY-SA 4.0
2021-04-20T13:16:41.750
75407
2021-04-20T13:16:41.750
43025
75374
answer


今回やりたかったことは幽霊型(Phantom Type)に近いと思い探していたところ、以下の記事を発見しました。

<https://zenn.dev/f_subal/articles/phantom_type_in_typescript>

これを参考に、

[code]

    type json_string = string & { _jsonBrand: never }
    
[/code]

が自分の欲しかったものだ、と思っています。

この `_ほげほげBrand` という命名規則のフィールドは、こういった型の色付けを行いたい場合に付与するフィールドとして、 typescript
の内部ライブラリでも利用されているものであるそうです。

参考: <https://basarat.gitbook.io/typescript/main-1/nominaltyping#using-
interfaces>


CC BY-SA 4.0
2021-06-14T08:46:37.780
77548
2021-06-14T08:46:37.780
754
75374
answer