我有以下示例来说明我想要获得的内容。
const v1: { type: "S"; payload: string } = { type: "S", payload: "test" };
const v2: { type: "N"; payload: number } = { type: "N", payload: 123 };
type Actions = typeof v1 | typeof v2;
const findByType = <A extends Actions>(type: A["type"]) => (
action: Actions
): action is A => action.type === type;
const filterWithBothNameAndType = [v1, v2].filter(findByType<typeof v1>("S"));
console.log(filterWithBothNameAndType[0].payload.trim());
const findByTypeDoesntWork = <A extends Actions, T extends A["type"]>(type: T) => (
action: Actions
): action is A => action.type === type;
const filterWithJustType = [v1, v2].filter(findByTypeDoesntWork("S"));
console.log(filterWithJustType[0].payload.trim());
我的函数findByType
具有正确的类型信息,我的函数filterWithJustType
具有我喜欢的api,但它丢失了类型信息。我希望api只是filter("S")
而不传递泛型类型。到目前为止it looks like它只适用于类和instaceof
,但我想让它适用于普通对象。
答案 0 :(得分:0)
它不起作用,因为它要求编译器假设如果扩展Actions
的某些类型具有文字类型type
的{{1}}成员,那么它必须是{ {1}}。
这个假设一般不安全,因为S
是一个非常弱的约束,并且编译:
typeof v1
顺便说一句,在extends Actions
打开的情况下,它不会在2.6中编译,但类型推断没有利用此选项引入的额外稳健性,并且不清楚它应该是什么。
但是有一种方法可以明确告诉编译器,只能从它的const v3: { type: "S"; payload: boolean } = { type: "S", payload: false };
const filterWithJustType3 = [v1, v2, v3].filter(findByTypeDoesntWork("S"));
成员类型中明确地推断出union成员。您只需要自己建立类型映射:
strictFunctionTypes
答案 1 :(得分:0)
感谢@artem让我了解了ActionMap,我添加了actionCreator,以确保密钥和有效负载类型同步,并且看到:
private void button1_Click(object sender, EventArgs e)
{
SqlConnection sqlcon = new SqlConnection (@"C:\LOGIN\DB\LOGINDB.MDF");
string query = "Select * from Table where username='" + txtUsername.Text + "'and password='" + txtPassword.Text + "'";
SqlDataAdapter sda = new SqlDataAdapter(query, sqlcon);
DataTable dtbl = new DataTable();
sda.Fill(dtbl);
if(dtbl.Rows.Count == 1)
{
frmMain objFrmMain = new frmMain();
this.Hide();
objFrmMain.Show();
}
else
{
MessageBox.Show("Check you things");
}
}
此解决方案确保type ActionMap = {
S: string;
N: number;
};
function actionCreatorFactory<
T extends keyof ActionMap,
P extends ActionMap[T]
>(type: T) {
return function actionCreator(payload: P) {
return { type, payload };
};
}
const actionCreators = {
s: actionCreatorFactory("S"),
n: actionCreatorFactory("N"),
};
const v1 = actionCreators.s("test");
const v2 = actionCreators.n(123);
const findByType = <
T extends keyof ActionMap,
A extends { type: T; payload: ActionMap[T] }
>(
type: T
) => (action: A): action is A => action.type === type;
const filterWithJustType = [v1, v2].filter(findByType("S"));
console.log(filterWithJustType[0].payload.trim());
是您必须声明类型的唯一位置,其他所有内容都将从中派生。
<强>更新强> 刚刚发布的文章中有更多这种方法的例子https://medium.com/@dhruvrajvanshi/some-tips-on-type-safety-with-redux-98588a85604c
答案 2 :(得分:0)
您可以使用docs中提到的Exclude
或Extract
,例如:
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
type T02 = Exclude<string | number | (() => void), Function>; // string | number
type T03 = Extract<string | number | (() => void), Function>; // () => void