2017-12-02 9 views
1

は、活字体コンパイラはconstsのために、文字列リテラルの型を推論します:プロパティの文字列リテラル型を推論するためにTypescriptコンパイラにヒントを教えてください。

const a = 'abc'; 
const b: 'abc' = a; // okay, a is of type 'abc' rather than string 

しかし、性質のために、型がstringと推定されます。この例では

const x = { 
    y: 'def', 
}; 

const z: { y: 'def' } = x; // error because x.y is of type string 

、どのように私は、コンパイラがxxのために型注釈を記述することなく、タイプ{ y: 'def' }であることを推論するために得ることができますか?

編集:issueがこの機能のサポートをリクエストしています。一つの解決策としては、このような構文を使用することです:

const x = new class { 
    readonly y: 'def'; 
}; 

const z: { readonly y: 'def' } = x; // Works 

は遊び場hereでそれを試してみてください。

編集2:この問題を解決するオープンPRもあります。型の拡大を無効にすることは一般的な要求のようです。

+0

[type assertion](https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions)で特定の型があることをコンパイラに伝えることができます: 'const x = { y: 'def' as 'def'、 }; ' – artem

答えて

2

違いはプロパティのキーワードがconstではありません。プロパティが変更されないことを確実にする方法がないため、TSは定数文字列リテラルを引き継ぐことはできません。より汎用的なものと仮定しなければなりません。string

すぎTSはstringを想定しようとしているletと、その場所で、あなたの例では、最初のconstを交換してみてくださいません'abc'

TS Playground link for this code

let a = 'abc'; 
const b: 'abc' = a; 
は「 bのエラーを表示するつもりですタイプ文字列はタイプ 'abc'に割り当てられません。

const変数の例のように、TSは言語機能から不変性を推論できないため、obejctプロパティが不変であることを明示的に示すのは、あなたの質問に対する答えがネガティブ。

1

はい、この問題(Microsoft/TypeScript#10195)は、それを維持したいと思っている人にとっては厄介です。DRY @artemは言及として、あなたはこれを行うことができます:

const x = { 
    y: 'def' as 'def' // WET 
}; 
const z: { y: 'def' } = x; // okay 

をそれが二回'def'に言及する必要があります。一度は値として、一度は型として。タイプ・スクリプトは、ジェネリック・クラスまたは関数のタイプ・パラメーターに対して、オブジェクト・リテラル内ではなく、より狭いタイプを推測するよう強制されることがあります。


カスタムライブラリともう少しオーバーヘッドと一緒に暮らすために喜んでいる場合は、あなたがこれを行うことができます:LitObjがそのように(好ましくは、独自のモジュールのように定義されて

const x = LitObj.of('y', 'def').build(); // DRY 
const z: { y: 'def' } = x; // okay 

をどこかに離れてあなたのコードから):

type Lit = string | number | boolean | undefined | null | {}; 
class LitObj<T> { 
    obj = {} as T; 
    private constructor() { 
    } 
    and<K extends string, V extends Lit>(k: K, v: V): LitObj<T & Record<K, V>> { 
    var that = this as any; 
    that.obj[k] = v; 
    return that; 
    } 
    build(): {[K in keyof T]: T[K]} { 
    return this.obj; 
    } 
    static of<K extends string, V extends Lit>(k: K, v: V): LitObj<Record<K,V>> { 
    return new LitObj<{}>().and(k,v); 
    } 
} 

アイデアはLitObjは文字通り型付けされたオブジェクトのためのビルダーであるということです。実行時にはオブジェクトにプロパティを追加するだけですが、定義によってTypeScriptでリテラルのキーと値の型を追跡することができます。とにかく、助けて欲しい。がんばろう!

関連する問題