TypeScriptバージョン: 2.1.1
コード
type A = { a: string; }
type B = { b: string; }
type AorB = A | B;
declare const AorB: AorB;
if (AorB.a) {
// use AorB.a
}
予想される行動:
コードはエラーなしでコンパイルされます。 a
は(必然的に)ユニオンのすべての構成要素に存在するわけではありませんが、一部に存在するという事実により、 .a
をチェックし、存在する場合はそれを使用できるはずです。
実際の動作:
Typescriptは、「プロパティaはタイプAorBに存在しません...プロパティaはタイプBに存在しません。」と文句を言います。
ドキュメントによると:
同じコードを機能させるには、型アサーションを使用する必要があります。
let pet = getSmallPet();
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
}
else {
(<Bird>pet).fly();
}
http://www.typescriptlang.org/docs/handbook/advanced-types.html
次に、サンプルで:
if ((<A>AorB).a) {
// use AorB.a
}
ここでの問題は、 B
がa
プロパティを宣言していないため、実行時に任意のタイプのa
プロパティが存在する可能性があることです(文字列型のb
プロパティがある限り、 B
へのプロパティのセットを持つオブジェクト)。 B
a: undefined
プロパティを明示的に宣言して機能させることができます(したがって、 B
にランダムなa
プロパティがないことを確認します)。
type A = { a: string; }
type B = { b: string; a: undefined }
type AorB = A | B;
declare const AorB: AorB;
if (AorB.a) {
// Ok
}
完全に理にかなっています。 脳のおなら。
タイプBでa: undefined
を定義する場合、変数を作成/渡すときにundefined
に設定する必要があります。
これを回避するには、 a
をa?: undefined
として宣言できます。これを省略した場合、typescriptは問題ありません。
コメントを正しく理解していれば、これは機能するはずです(ただし、スローされます。遊び場でテストされます):これはバグですか? 🤔
type LinkProps = {
to: string;
onClick?: undefined;
// Link specific props:
target: string;
}
type ButtonProps = {
to?: undefined;
onClick: Function;
// Button specific props:
disabled: boolean;
}
type ActionProps = LinkProps | ButtonProps;
const Action = (props: ActionProps) =>
props.to ?
'Link with target: ' + props.target // Error not on ButtonProps
:
'Button with disabled: ' + props.disabled; // Error: not on LinkProps
Action({
to: 'dssd',
target: '_blank'
});
私はこれをまったく理解していません。 if ((<A>AorB).a)
は、 A
と入力するように強制しているため、 (A.a)
場合と同じではありませんか?
タイプBで
a: undefined
を定義する場合、変数を作成/渡すときにundefined
に設定する必要があります。
これを回避するには、a
をa?: undefined
として宣言できます。これを省略した場合、typescriptは問題ありません。
a?: never
方が良いかもしれませんが、誤ってundefined
割り当てることはできません
組合の各メンバーに名前を付けないとどうなりますか? (アサートされた型の名前がないと、上記のように型アサーションを作成できませんか?)
type u = "str" | {prop:"val"};
function f(arg:u){return arg.prop} // TypeScript: Property 'prop' does not exist on type 'u'
解決策はありますか?
私は本で解決策を見つけます:
interface A { x: number;}
interface B { y: string;}
function doStuff ( q: A | B ) {
if ( 'x' in q) {
// if type A...
}
else {
// if type B...
}
}
抜粋:Basarat AliSyed。 「TypeScriptディープダイブ。」 アップルブックス。
オブジェクトのプロパティであり、タイプガードとして使用でき、TypeScriptは使用したタイプを認識できます。
type ColorItemType = {
colorId: number,
colorName: string,
}
type NumItemType = {
numId: number,
numName: string
}
type ResType = {
itemId: number,
// 0 color 1 num
type: number,
itemInfo: {
colorList: Array<ColorItemType>
numList: Array<NumItemType>
}
}
const request = () => {
return [{
itemId: 1,
type: 0,
itemInfo: {
colorList: [{
colorId: 1,
colorName: 'blue'
}],
numList: []
}
}];
};
const dataSource: Array<ResType> = request();
const formatData = dataSource.map(dataItem => {
const list: Array<ColorItemType | NumItemType> = dataItem.type === 1 ? dataItem.itemInfo.numList : dataItem.itemInfo.colorList;
return list.map(listItem => {
return {
// An error will be reported here
value: listItem.numId || listItem.colorId,
label: listItem.numName || listItem.colorName
};
});
});
ここでの問題は、
B
がa
プロパティを宣言していないため、実行時に任意のタイプのa
プロパティが存在する可能性があることです(文字列型のb
プロパティがある限り、B
へのプロパティのセットを持つオブジェクト)。B
a: undefined
プロパティを明示的に宣言して機能させることができます(したがって、B
にランダムなa
プロパティがないことを確認します)。type A = { a: string; } type B = { b: string; a: undefined } type AorB = A | B; declare const AorB: AorB; if (AorB.a) { // Ok }
私のために動作しません07.10.2020
そして、このTSの動作は、開発者の役に立たないため、良くないと思います...
最も参考になるコメント
私は本で解決策を見つけます:
抜粋:Basarat AliSyed。 「TypeScriptディープダイブ。」 アップルブックス。
オブジェクトのプロパティであり、タイプガードとして使用でき、TypeScriptは使用したタイプを認識できます。