Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 将类型缩小为具有某些属性的对象_Typescript - Fatal编程技术网

Typescript 将类型缩小为具有某些属性的对象

Typescript 将类型缩小为具有某些属性的对象,typescript,Typescript,我试图弄明白为什么typescript不喜欢下面的结构。编译器错误在代码中的注释中 const BAR = Symbol(); function foo<T>(that: T) { if (that !== null && typeof that === "object" && BAR in that) { // Element implicitly has an 'any' type because expressi

我试图弄明白为什么typescript不喜欢下面的结构。编译器错误在代码中的注释中

const BAR = Symbol();

function foo<T>(that: T) {
  if (that !== null && typeof that === "object" && BAR in that) {
    // Element implicitly has an 'any' type because expression of type 'unique symbol' can't be used to index type 'unknown'.
    // Property '[BAR]' does not exist on type 'unknown'.ts(7053)
    const bar = that[BAR];
    console.log(bar);
  }
}

function foo2<T>(that: T) {
  if (that !== null && typeof that === "object" && "BAR" in that) {
    // Element implicitly has an 'any' type because expression of type '"BAR"' can't be used to index type 'unknown'.
    // Property 'BAR' does not exist on type 'unknown'.ts(7053)
    const bar = that["BAR"];
    console.log(bar);
  }
const BAR=Symbol();
函数foo(即:T){
if(that!==null&&typeof that===“object”&&BAR in that){
//元素隐式具有“any”类型,因为“unique symbol”类型的表达式不能用于索引类型“unknown”。
//类型“未知”上不存在属性“[BAR]”。ts(7053)
常数bar=该[bar];
控制台日志(bar);
}
}
函数foo2(即:T){
if(that!==null&&typeof that===“object”&&BAR”在该字段中){
//元素隐式具有“any”类型,因为类型为“BAR”的表达式不能用于索引类型“unknown”。
//类型“未知”上不存在属性“BAR”。ts(7053)
常数条=该[“条”];
控制台日志(bar);
}

if
是否应该足够缩小类型范围?

由于泛型函数没有约束,TS不知道t将是什么。因此它会抱怨。TS进行静态类型分析,而不是运行时分析。if语句不属于前一类

TypeScript的强大之处在于它的明确性,因此,如果您已经知道将传递给函数(
,该函数是
)的属性具有特定的键(
),那么您应该做出声明

如果您想坚持使用泛型,例如可以这样做:

const BAR='BAR';
接口断路器{
[酒吧]:任何,
}
函数foo(即:T){
if(that!==null&&typeof that===“object”&&BAR in that){
常数bar=该[bar];
控制台日志(bar);
}
}
/*
字符串替代项:
接口断路器{
酒吧:任何,
}
..然后是上面的字符串函数
*/
请注意,TS不允许接口将符号用作键


一些额外的想法


我不知道你在这里使用泛型的原因,但是如果你知道你将把这个函数传递给一个对象,并且你对这个函数的结构有一些了解,你也可以只使用一个接口,怎么样?这不可能是最好的解决方案,但它确实有效

const BAR=Symbol();
函数foo(即:T){
if(that!==null&&typeof that==“object”&&hasProperty(that,BAR)){
常数bar=该[bar];
控制台日志(bar);
}
}
函数foo2(即:T){
if(that!==null&&typeof that==“object”&&hasProperty(that,“BAR”)){
常数条=该[“条”];
控制台日志(bar);
}
}
函数hasProperty(obj:any,prop:P):obj是{[;in P]:unknown}{
obj中的返回道具;
}

您应该将收到的错误添加到问题中错误在comments@user3612643,我认为TS编译器在编写时不能很好地支持符号索引。@miqh编译器还抱怨foo2使用了字符串。请检查类型谓词:您的答案指向错误的方向。请考虑r“that:T | Barable”而不是“T extensed Barable”。如果“T extensed Barable”,则显然,If始终为真。您没有真正给出任何上下文,因此我假设您的If语句是为了修复错误。正如我所说的“如果您已经知道将传递给函数(该函数)的属性具有特定的键(BAR),你应该做出声明。”-如果不是的话,那显然不是。与其对我的答案投反对票并抱怨,你可以更好地描述你的问题,也许有人能给你更好的答案。看起来不错,但实际上我认为ts编译器应该自动检测到它。。。
const BAR = Symbol();
function foo<T>(that: T) {
  if (that !== null && typeof that === "object" && hasProperty(that, BAR)) {
    const bar = that[BAR];
    console.log(bar);
  }
}

function foo2<T>(that: T) {
  if (that !== null && typeof that === "object" && hasProperty(that, "BAR")) {
    const bar = that["BAR"];
    console.log(bar);
  }
}

function hasProperty<P extends keyof any>(obj: any, prop: P): obj is { [_ in P]: unknown } {
    return prop in obj;
}