class A<T>
{
some: { [K in keyof T]: (x: T[K]) => T[K] }
}
interface IB {
b: number
}
class B<T extends IB> extends A<T>
{
constructor()
{
super()
/**
* Type '{ b: (x: T["b"]) => number; }'
* is not assignable to type '{ [K in keyof T]: (x: T[K]) => T[K]; }'.
*/
this.some = {
b: x => 2*x
}
}
}
interface IC {
b: number
c: boolean
}
class C<T extends IC> extends B<T>
{
constructor()
{
super()
/**
* Type '{ b: (x: T["b"]) => number; c: (x: T["c"]) => boolean; }'
* is not assignable to type '{ [K in keyof T]: (x: T[K]) => T[K]; }'
*/
this.some = {
b: x => 4*x,
c: x => !x
}
}
}
您好。我尝试在基类“A”中设置泛型约束,目的是在派生类中自动推断“某些”属性的类型。不幸的是我无法理解为什么我会像上面提到的那样得到TS错误。从我的观点来看,一切似乎都很好。
谢谢!
答案 0 :(得分:2)
如果我这样做会怎么样?
const b = new B<{ b: 3, z: string }>();
正如您所看到的,我传递了{ b: 3, z: string }
类型,这是可以接受的,因为它扩展了{ b: number }
。这意味着b.some.b
应该是(x: 3) => 3
类型。这也意味着b.some.z
应该是(x: string) => string
类型。对B
的实施是否正确?没有; b.some.b
实际上是(x: 3) => number
类型,b.some.z
未定义。所以编译器警告你是有道理的。
首先,让我们来处理z: string
问题。也许在A
中,您希望some
的属性是可选的,如下所示:
class A<T>
{
some: {[K in keyof T]?: (x: T[K]) => T[K]}
}
这样,您的B
和C
构造函数就可以初始化some
,而无需了解额外的属性。
现在,关于b: 3
。如果您想允许某人扩展number
,那么您可以使用的唯一安全的是身份功能:
this.some = {};
this.some.b = x => x; // okay
但是,您可能不希望任何人传递number
类型的b
更具体的内容。b
。不幸的是,没有什么好办法可以阻止它。所以,很好,只是文档,用户应该只传递number
可以是任何this
的类型。在这种情况下,您需要告诉编译器不要担心,声明B<IB>
类型为this.some = {};
(this as B<IB>).some.b = x => 2 * x; // okay
:
C
可以为您的DECLARE @T_Find_Text VARCHAR(1000) = 'Foo'
IF OBJECT_ID('tempdb..#T_DBNAME') IS NOT NULL DROP TABLE #T_DBNAME
IF OBJECT_ID('tempdb..#T_PROCEDURE') IS NOT NULL DROP TABLE #T_PROCEDURE
CREATE TABLE #T_DBNAME
(
IDX int IDENTITY(1,1) PRIMARY KEY
, DBName VARCHAR(255)
)
CREATE TABLE #T_PROCEDURE
(
IDX int IDENTITY(1,1) PRIMARY KEY
, DBName VARCHAR(255)
, Procedure_Name VARCHAR(MAX)
, Procedure_Description VARCHAR(MAX)
)
INSERT INTO #T_DBNAME (DBName)
SELECT name FROM master.dbo.sysdatabases
DECLARE @T_C_IDX INT = 0
DECLARE @T_C_DBName VARCHAR(255)
DECLARE @T_SQL NVARCHAR(MAX)
DECLARE @T_SQL_PARAM NVARCHAR(MAX)
SET @T_SQL_PARAM =
' @T_C_DBName VARCHAR(255)
, @T_Find_Text VARCHAR(255)
'
WHILE EXISTS(SELECT TOP 1 IDX FROM #T_DBNAME WHERE IDX > @T_C_IDX ORDER BY IDX ASC)
BEGIN
SELECT TOP 1
@T_C_DBName = DBName
FROM #T_DBNAME WHERE IDX > @T_C_IDX ORDER BY IDX ASC
SET @T_SQL = ''
SET @T_SQL = @T_SQL + 'INSERT INTO #T_PROCEDURE(DBName, Procedure_Name, Procedure_Description)'
SET @T_SQL = @T_SQL + 'SELECT SPECIFIC_CATALOG, ROUTINE_NAME, ROUTINE_DEFINITION '
SET @T_SQL = @T_SQL + 'FROM ' + @T_C_DBName + '.INFORMATION_SCHEMA.ROUTINES '
SET @T_SQL = @T_SQL + 'WHERE ROUTINE_DEFINITION LIKE ''%''+ @T_Find_Text + ''%'' '
SET @T_SQL = @T_SQL + 'AND ROUTINE_TYPE = ''PROCEDURE'' '
BEGIN TRY
EXEC SP_EXECUTESQL @T_SQL, @T_SQL_PARAM, @T_C_DBName, @T_Find_Text
END TRY
BEGIN CATCH
SELECT @T_C_DBName + ' ERROR'
END CATCH
SET @T_C_IDX = @T_C_IDX + 1
END
SELECT IDX, DBName, Procedure_Name FROM #T_PROCEDURE ORDER BY DBName ASC
课程执行类似的修复。希望有所帮助;祝你好运!