Typescript泛型条件不精确类型

slwdgvem  于 2023-05-30  发布在  TypeScript
关注(0)|答案(2)|浏览(195)

下面是一段代码(playground,Typescript 5.0.4),它接受一个泛型函数,并根据类型执行一些操作:

type TypeToValue = {
  one: number;
  two: string;
};
function MyFunction<T extends keyof TypeToValue>(
  value: TypeToValue[T],
  type: T,
) {
  if (type === 'one') return value.toFixed(2); // fail "Property 'toFixed' does not exist on type 'string | number'."
  if (type === 'two') return value.toString()
  throw Error('invalid type')
}

但是,我希望它不会失败,因为Typescript应该知道在type === 'one'之后,泛型T'one',因此value类型为number
我的推理正确吗?是否有自动推断类型的解决方法?
谢谢!

7cjasjjr

7cjasjjr1#

我认为这个推论不够聪明,无法理解正确的类型。然而,这只是我的拙见。
无论如何,这里有一个稍微不同的版本,它只是在运行时计算类型。这也保证了正确的推理。

type TypeToValue = {
  one: number;
  two: string;
};
function MyFunction<T extends keyof TypeToValue>(
  value: TypeToValue[T],
  //  type: T,
) {
  if (typeof value === 'number') return value.toFixed(2);
  if (typeof value === 'string') return value.toString()
  throw Error('invalid type')
}

let s: string;
s = MyFunction<"one">(123.456);
console.log(s);    //prints "123.46" 

s = MyFunction<"two">("hello");
console.log(s);    //prints "hello"

也不需要第二个理由。

k75qkfdt

k75qkfdt2#

你需要一些更通用的东西来完成你的任务。Playground

interface Interface1 {
    a: string;
    b: number;
}

interface Interface2 {
    c: boolean;
    d: any;
}

function isInterface<T>(value: any): value is T {
    if (typeof value !== 'object' || value === null) {
        return false;
    }
    for (const key in value) {
        if (value[key] === undefined) {
            return false;
        }
    }
    return true;
}

type TypeToValue = number | string | Interface1 | Interface2;    

function MyFunction(t: TypeToValue) {
    if (typeof t === "number") {
        return t.toFixed(2);
    }

    if (typeof t === "string") {
        return t.toString();
    }

    if (isInterface<Interface1>(t)) {
        console.log('processing obj of type Interface1');
        return t; // or do something with object of type Interface1
    }

    if (isInterface<Interface2>(t)) {
        console.log('processing obj of type Interface2');
        return t; // or do something with object of type Interface2
    }

    throw new Error("Invalid type");
}

// test
const obj1 = { a: 'hello', b: 100 };
const obj2 = { c: true, d: 'world' };
console.log(MyFunction(100));
console.log(MyFunction("one hundred"));
console.log(MyFunction(obj1));
console.log(MyFunction(obj2));

相关问题