Help with oop and type checking

I keep running into this issue saying “attempt to call a nil value” when I run Item.Init()

Here is more in detail, this is my gun class

local gun = { guns = {} }
gun.__index = gun

--Type "self" has all of the properties of a gun
type self = {
    Aiming: boolean,
    Reloading: boolean,
    Shooting: boolean,
    AnimationDebouncing: boolean,
    Gun: Model?,
    LoadedAnimations: table,
    animationSettings: { [string]: number },
    GunName: string,
    WeaponType: string,
    Ammo: number,
    MaxAmmo: number,
    Damage: number,
    ReloadTime: number,
    ShootCooldownTime: number,
    C0: CFrame,
    Auto: boolean,
    Carriable: number,
    ChangeFOV: number,
}

export type newGun = typeof(setmetatable({} :: self, gun))

--gunInfo is gun info from gameConfig.lua
function gun.new(gunInfo: self): newGun
    local self = setmetatable({} :: self, gun)

    self = gunInfo

    self._janitor = Janitor.new()
    self._bulletDropCache = PartCache.new(ReplicatedStorage.BulletTemplate, self.MaxAmmo * 2)

    self.Aiming = false
    self.Reloading = false
    self.Shooting = false
    self.AnimationDebouncing = false --* For animations like equipping/unequipping
    self.Gun = "n/a" --This is an instance
    self.LoadedAnimations = {}

    --* Adding newGun to the guns table where we store all of the players guns
    gun.guns[self.GunName] = self

    return self
end

-- to call this I use item.Init()
function gun:Init()
print("do stuff")
end

And here is my firstPerson class

local firstPerson = {}
firstPerson.__index = firstPerson

type self = {
    Holding: GunClient.newGun,
    Arms: Model?,
}

export type person = typeof(setmetatable({} :: self, firstPerson))

function firstPerson.new()
    local person = setmetatable({} :: self, firstPerson)

    person._janitor = Janitor.new()
    person._gunJanitor = Janitor.new() --Janitor for gun instances (Motor6D's etc.)

    person.Holding = "n/a" --* Holding item (class)
    person.Arms = "n/a"

    firstPerson.Person = person

    return person
end

function firstPerson:Equip(item: GunClient.newGun) --self: person, 
    print(item)
    item.Init()
end

To call this firstPerson:Equip, I used this inside of a different modulescript that isn’t a class
self:Equip(item)

I’ve tried

self.Equip(item)

but then when I print item in the function it would return as nil, but when I ran self:Equip(item) it didn’t return as nil

Btw item is gun.new() stored in a table,
Also GunClient is the gun class cript

Can someone help me! Thanks

Okay, so I’ve found the issue.

After testing I found out that when I run

local newGun = GunClient.new(gunInfo)
newGun.Init()

I get an error saying it’s not a method of table, now idk what to do.

I think the problem is this line of your code:

Because now you’re saying ‘self’ is the gunInfo. This means self isn’t the metatable with your :Init() method. gunInfo doesn’t have the :Init() method.

We want ‘self’ to stay as: