如何在typescript

时间:2017-11-09 01:21:01

标签: typescript

我有以下示例来说明我想要获得的内容。

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());

typescript playground

我的函数findByType具有正确的类型信息,我的函数filterWithJustType具有我喜欢的api,但它丢失了类型信息。我希望api只是filter("S")而不传递泛型类型。到目前为止it looks like它只适用于类和instaceof,但我想让它适用于普通对象。

3 个答案:

答案 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中提到的ExcludeExtract,例如:

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