回答:
と表記することもできますobj
がany
、それはtypescriptを使用する目的全体を無効にします。obj = {}
はを意味obj
しObject
ます。マークを付けてany
も意味がありません。望ましい一貫性を実現するために、インターフェースを次のように定義できます。
interface LooseObject {
[key: string]: any
}
var obj: LooseObject = {};
またはコンパクトにする:
var obj: {[k: string]: any} = {};
LooseObject
キーとして任意の文字列any
、値としてタイプのフィールドを受け入れることができます。
obj.prop = "value";
obj.prop2 = 88;
このソリューションの真の優雅さは、インターフェースにタイプセーフフィールドを含めることができることです。
interface MyType {
typesafeProp1?: number,
requiredProp1: string,
[key: string]: any
}
var obj: MyType ;
obj = { requiredProp1: "foo"}; // valid
obj = {} // error. 'requiredProp1' is missing
obj.typesafeProp1 = "bar" // error. typesafeProp1 should be a number
obj.prop = "value";
obj.prop2 = 88;
これは元の質問に答えますが、@ GreeneCreationsによるここでの答えは、問題へのアプローチ方法に別の視点を与える可能性があります。
LooseObject
、エラーも発生する可能性があります。
または一度にすべて:
var obj:any = {}
obj.prop = 5;
any
を使用するために多くのものをキャストする必要がある場合、TypeScriptのポイントは何ですか?ちょうど私のコードで余分なノイズになります..:/
any
。TypeScriptは、コンパイル時に(潜在的な)エラーをキャッチするために使用されます。any
エラーをミュートするためにキャストすると、タイピングの能力が失われ、純粋なJSに戻ることもできます。any
TS定義を記述できないコードをインポートする場合、またはコードをJSからTSに移行するときにのみ使用するのが理想的です
私はany
反対側に置く傾向があります。つまり、var foo:IFoo = <any>{};
このようなものはまだタイプセーフです:
interface IFoo{
bar:string;
baz:string;
boo:string;
}
// How I tend to intialize
var foo:IFoo = <any>{};
foo.bar = "asdf";
foo.baz = "boo";
foo.boo = "boo";
// the following is an error,
// so you haven't lost type safety
foo.bar = 123;
または、これらのプロパティをオプションとしてマークすることもできます。
interface IFoo{
bar?:string;
baz?:string;
boo?:string;
}
// Now your simple initialization works
var foo:IFoo = {};
I still have <any>{
その後、あなたはコンパイルしていません。TypeScriptはそれをその放出で削除します
var foo: IFoo = {} as any
は好ましいです。型キャストの古い構文はTSX(Typescript-ified JSX)と衝突していました。
このソリューションは、オブジェクトに特定のタイプがある場合に役立ちます。他のソースにオブジェクトを取得するときのように。
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
コンパイラーは不平を言いますが、必要に応じて出力する必要があります。ただし、これは機能します。
var s = {};
s['prop'] = true;
JavaScriptで「構成」について考えるときはいつもそれを使用する手法であるため、どの回答もObject.assignを参照していないことに驚いています。
そして、それはTypeScriptで期待通りに機能します:
interface IExisting {
userName: string
}
interface INewStuff {
email: string
}
const existingObject: IExisting = {
userName: "jsmith"
}
const objectWithAllProps: IExisting & INewStuff = Object.assign({}, existingObject, {
email: "jsmith@someplace.com"
})
console.log(objectWithAllProps.email); // jsmith@someplace.com
メリット
any
をまったく使用する必要がないため、全体にわたって型の安全性を確保する&
のタイプを宣言するときにで示されるobjectWithAllProps
)を使用して、新しいタイプをオンザフライで(つまり動的に)作成していることを明確に伝える注意すること
existingObject
そのままの状態でemail
プロパティがないためです。ほとんどの関数形式のプログラマーにとって、結果は唯一の新しい変更)。スプレッド演算子を使用して、古いオブジェクトに基づいて新しいオブジェクトを作成できます
interface MyObject {
prop1: string;
}
const myObj: MyObject = {
prop1: 'foo',
}
const newObj = {
...myObj,
prop2: 'bar',
}
console.log(newObj.prop2); // 'bar'
TypeScriptは元のオブジェクトのすべてのフィールドを推測し、VSCodeはオートコンプリートなどを行います。
最も簡単なのは
const obj = <any>{};
obj.prop1 = "value";
obj.prop2 = "another value"
既存のオブジェクトにメンバーを追加することは可能です
interface IEnhancedPromise<T> extends Promise<T> {
sayHello(): void;
}
const p = Promise.resolve("Peter");
const enhancedPromise = p as IEnhancedPromise<string>;
enhancedPromise.sayHello = () => enhancedPromise.then(value => console.info("Hello " + value));
// eventually prints "Hello Peter"
enhancedPromise.sayHello();
あなたはこれを行うことができないので:
obj.prop = 'value';
TSコンパイラとリンターで制限されていない場合は、次のように記述できます。
obj['prop'] = 'value';
TSコンパイラまたはリンターが厳密な場合、別の答えは型キャストすることです:
var obj = {};
obj = obj as unknown as { prop: string };
obj.prop = "value";
'any'に型キャストすることにより、任意の種類のオブジェクトに新しいプロパティを格納します。
var extend = <any>myObject;
extend.NewProperty = anotherObject;
後で、拡張オブジェクトを 'any'にキャストして戻すことができます。
var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;
この宣言を追加して警告を止めることができます。
declare var obj: any;
ベストプラクティスは安全なタイピングを使用することです。
interface customObject extends MyObject {
newProp: string;
newProp2: number;
}
これはの特別なバージョンでObject.assign
、プロパティが変更されるたびに変数の型が自動的に調整されます。追加の変数、型の表明、明示的な型、オブジェクトのコピーは必要ありません。
function assign<T, U>(target: T, source: U): asserts target is T & U {
Object.assign(target, source)
}
const obj = {};
assign(obj, { prop1: "foo" })
// const obj now has type { prop1: string; }
obj.prop1 // string
assign(obj, { prop2: 42 })
// const obj now has type { prop1: string; prop2: number; }
obj.prop2 // number
// const obj: { prop1: "foo", prop2: 42 }
注:このサンプルでは、TS 3.7 アサーション関数を使用しています。の戻り値の型はassign
とvoid
は異なりObject.assign
ます。
Typescriptを使用している場合は、おそらくタイプセーフを使用する必要があります。その場合、裸のObjectと 'any'は反証されます。
Objectや{}ではなく、名前付きの型を使用する方がよいでしょう。または、独自のフィールドで拡張する必要がある特定のタイプのAPIを使用している可能性があります。私はこれがうまくいくことを発見しました:
class Given { ... } // API specified fields; or maybe it's just Object {}
interface PropAble extends Given {
props?: string; // you can cast any Given to this and set .props
// '?' indicates that the field is optional
}
let g:Given = getTheGivenObject();
(g as PropAble).props = "value for my new field";
// to avoid constantly casting:
let k:PropAble = getTheGivenObject();
k.props = "value for props";
TypeScriptでオブジェクトにプロパティを動的に割り当てます。
そのためには、次のようにtypescriptインターフェースを使用する必要があります。
interface IValue {
prop1: string;
prop2: string;
}
interface IType {
[code: string]: IValue;
}
そんな風に使えます
var obj: IType = {};
obj['code1'] = {
prop1: 'prop 1 value',
prop2: 'prop 2 value'
};
attributes
フィールドの内部をSomeClass
、それはそれを修正する必要がありpublic attributes: IType = {};
pastebin.com/3xnu0TnN
完全にタイプセーフな唯一のソリューションはこれですですが、少し複雑で、複数のオブジェクトを作成する必要があります。
最初に空のオブジェクトを作成する必要がある場合は、これら2つのソリューションのいずれかを選択してください。使用するたびにas
、安全性が失われるしてください。
タイプがobject
あり、安全な内部getObject
手段は、object.a
型になりますstring | undefined
interface Example {
a: string;
b: number;
}
function getObject() {
const object: Partial<Example> = {};
object.a = 'one';
object.b = 1;
return object as Example;
}
のタイプは内部で安全でobject
はありませんgetObject
。つまり、割り当て前でもobject.a
タイプになりますstring
。
interface Example {
a: string;
b: number;
}
function getObject() {
const object = {} as Example;
object.a = 'one';
object.b = 1;
return object;
}